Как можно получить уникальные значения из таблицы данных с помощью dql?
Вопрос
У меня есть таблица, в которой есть столбец, в котором хранятся различные значения.я хочу извлечь уникальные значения из этой таблицы, используя dql.
Doctrine_Query::create()
->select('rec.school')
->from('Records rec')
->where("rec.city='$city' ")
->execute();
Теперь мне нужны только уникальные значения.Кто-нибудь может сказать мне, как это сделать...
Редактировать
Структура таблицы:
CREATE TABLE IF NOT EXISTS `records` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`state` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`city` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`school` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=16334 ;
Это запрос, который я использую:
Doctrine_Query::create()
->select('DISTINCT rec.city')
->from('Records rec')
->where("rec.state = '$state'")
// ->getSql();
->execute();
Генерация Sql для этого дает мне:
SELECT DISTINCT r.id AS r__id, r.city AS r__city FROM records r WHERE r.state = 'AR'
Теперь проверьте сгенерированный sql:::: ОТЧЕТЛИВЫЙ находится в столбце 'id', где, как я хочу, указано в столбце city.Кто-нибудь знает, как это исправить.
РЕДАКТИРОВАТЬ 2
Идентификатор уникален, потому что это автоматически добавляемое значение.Да, у меня есть несколько реальных дубликатов в столбце city, например:Дели и Delhi.Правильно..Теперь, когда я пытаюсь извлечь из него данные, я получаю Delhi два раза.Как я могу сделать запрос, подобный этому:
select DISTINCT rec.city where state="xyz";
Потому что это даст мне правильный результат.
РЕДАКТИРОВАТЬ 3:
Кто-нибудь, кто может сказать мне, как разобраться в этом запросе ..???
Решение
Зависит от того, какую версию вы используете, но у меня была такая же проблема, и ->distinct() сработала у меня.
Doctrine_Query::create()
->select('rec.city')->distinct()
->from('Records rec')
->where("rec.state = '$state'")
->execute();
Другие советы
Не могли бы вы использовать ГРУППУ BY?
Doctrine_Query::create()
->select('rec.school')
->from('Records rec')
->where("rec.city='$city' ")
->groupBy('rec.school')
->execute();
В RawSql нет необходимости
Вместо ->выбрать('DISTINCT rec.city')
Использовать -> выбрать('ОТЛИЧИТЬ (rec.city) как город')
Вы можете использовать Raw_Sql ( исходный код ) класс для достижения этой цели.Вот тест, который я только что провел на своей собственной базе данных:
<?php
set_include_path(get_include_path() . PATH_SEPARATOR . 'library');
require('Doctrine.php');
spl_autoload_register(array('Doctrine', 'autoload'));
Doctrine::loadModels('application/models/generated');
Doctrine::loadModels('application/models');
$dm=Doctrine_Manager::getInstance();
$conn = $dm->openConnection("mysql://dbuser:dbpass@localhost/database"); //changed actual values...
$q = new Doctrine_RawSql($conn);
$q->select('{c.name}')
->distinct()
->from('contactlist c')
->addComponent('c', 'Contactlist');
//this outputs: SELECT DISTINCT c.name AS c__name FROM contactlist c
echo $q->getSqlQuery() . "<br>\n";
$contacts = $q->execute();
foreach($contacts->toArray() as $contact){
echo $contact['name'] . "<br>\n";
}
?>
DISTINCT - это агрегирующая функция.Как таковая Доктрина не может преобразовать ваш результат в объекты.Используйте другую стратегию увлажнения, как предложил бартман.
$q = Doctrine_Query::create()
->select('DISTINCT rec.city')
->from('Records rec')
->execute(array(), Doctrine_Core::HYDRATE_SCALAR);
у меня все работало нормально
Причина, по которой Doctrine всегда добавляет первичный ключ в список полей, лежит внутри Гидратации.Когда Doctrine извлекает строки из базы данных, она гидратирует (= преобразует) их в иерархию объектов и ссылается на объекты модели, используя первичный ключ.В вашем случае такое поведение нежелательно, поскольку представляют интерес только названия городов.
Я предлагаю два решения, к сожалению, я не могу протестировать их прямо сейчас.
- Попробуйте использовать Doctrine_RawSql Доктрина_RawSql.RawSql имеет специальную обработку для РАЗНЫХ запросов.
$q = Doctrine_RawSql::create()
->select('DISTINCT {rec.city}')
->from('Records rec')
->where('rec.state = ?', $state)
->addComponent('rec', 'Record');
$cities = $q->execute()
- Используйте гидратор, не основанный на иерархии объектов.Это может помешать Doctrine извлечь поле первичного ключа для инициализации класса модели.Смотрите документацию (не могу опубликовать ссылку - новый пользователь.извините.) для получения дополнительной информации.
$q = Doctrine_Query::create()
->select('DISTINCT rec.city')
->from('Records rec')
->where("rec.state = ?", $state);
$cities = $q->execute(array(), Doctrine_Core::HYDRATE_SCALAR);
$cities должны содержать массив массивов с ключами типа 'rec_city'.
Пожалуйста, обратите внимание на использование ?
заполнитель в операторах where рекомендуется позволять Doctrine выполнять экранирование и не бороться с этим самостоятельно.
$query = $this->getEntityManager()->createQueryBuilder()
->select('DISTINCT(p.document)')
->from('Products', 'p');
Это работает для меня.
Повторно отвеченный:
Проверил это на моем локальном компьютере - не сработало.Поэтому позвольте мне посоветовать использовать PDO до тех пор, пока это не будет улучшено или исправлено:
$dbh = Doctrine_Manager::connection()->getDbh();
$stmt = $dbh->prepare('SELECT DISTINCT(rec.city) FROM <tablename> WHERE rec.state = :state');
$stmt->bindParam(':state', $state);
$stmt->execute();
$result = $stmt->fetchAll();
Совет
Я бы порекомендовал вам использовать внешний ключ ссылка на список городов на city
столбец вместо обычного текста для гибкости и повышения производительности.