Как можно получить уникальные значения из таблицы данных, используя dql? - PullRequest
11 голосов
/ 27 января 2010

У меня есть таблица, в которой есть столбец, в котором хранятся различные значения. Я хочу получить уникальные значения из этой таблицы, используя 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 :::: DISTINCT находится в столбце 'id', где, как я хочу, Distinct в столбце city. Кто-нибудь знает, как это исправить.

EDIT2

Идентификатор уникален, потому что он имеет автоинкрементное значение. У меня есть реальные дубликаты в столбце города, такие как: Дели и Дели. Правильно .. Теперь, когда я пытаюсь получить данные из него, я получаю Дели два раза. Как я могу сделать запрос так:

  select DISTINCT rec.city where state="xyz";

Потому что это даст мне правильный вывод.

EDIT3:

Кто-нибудь, кто может сказать мне, как выяснить этот запрос .. ???

Ответы [ 8 ]

15 голосов
/ 27 июня 2011

Зависит от того, какую версию вы используете, но у меня была та же проблема, и -> Different () работал для меня.

Doctrine_Query::create()
      ->select('rec.city')->distinct()
      ->from('Records rec')                   
      ->where("rec.state = '$state'")                                    
       ->execute();     
5 голосов
/ 09 июня 2010

Не могли бы вы использовать GROUP BY?

Doctrine_Query::create()
    ->select('rec.school')
    ->from('Records rec')                   
    ->where("rec.city='$city' ")                                    
    ->groupBy('rec.school')   
    ->execute();
3 голосов
/ 12 мая 2010

Нет необходимости в RawSql
Вместо -> выберите ('DISTINCT rec.city')
Используйте -> выберите («DISTINCT (rec.city) как город»)

2 голосов
/ 05 марта 2010

DISTINCT является функцией агрегирования. Как таковая Доктрина не может гидратировать ваш результат в объекты. Используйте другую стратегию увлажнения, как предложил Бартман.

$q = Doctrine_Query::create()
->select('DISTINCT rec.city')
->from('Records rec')
->execute(array(), Doctrine_Core::HYDRATE_SCALAR);

отлично сработало для меня

2 голосов
/ 02 февраля 2010

Вы можете использовать класс 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";
}

?>
1 голос
/ 20 мая 2013
$query = $this->getEntityManager()->createQueryBuilder()
                    ->select('DISTINCT(p.document)')
                    ->from('Products', 'p');

Этот работает для меня.

1 голос
/ 02 февраля 2010

Причина, по которой Doctrine всегда добавляет первичный ключ в список полей, заключается в гидратации.Когда Doctrine выбирает строки из базы данных, они гидратируют (= преобразуют) их в иерархию объектов и ссылаются на объекты модели с помощью первичного ключа.В вашем случае такое поведение нежелательно, поскольку интерес представляют только названия городов.

Я предлагаю два решения, к сожалению, пока не могу их протестировать.

  1. Попробуйте использовать Doctrine_RawSql .RawSql имеет специальную обработку для запросов DISTINCT.

$q = Doctrine_RawSql::create()<br> ->select('DISTINCT {rec.city}')<br> ->from('Records rec')<br> ->where('rec.state = ?', $state) ->addComponent('rec', 'Record');

$cities = $q->execute()

Использовать не основанный на иерархии объектов объект Hydrator.Это может помешать Doctrine получить поле первичного ключа для инициализации класса модели.См. Документацию (не может опубликовать ссылку - новый пользователь. Извините.) Для получения дополнительной информации.

$q = Doctrine_Query::create()<br> ->select('DISTINCT rec.city')<br> ->from('Records rec')<br> ->where("rec.state = ?", $state);

$cities = $q->execute(array(), Doctrine_Core::HYDRATE_SCALAR);

$ городовдолжен содержать массив массивов с ключами, такими как 'rec_city'.

Обратите внимание на использование заполнителя ? в операторах where. Хорошей практикой является позволить Doctrine выполнять экранирование, а не бороться с ним самостоятельно.

0 голосов
/ 29 января 2010

Re-ответил

Проверено это на моем локальном компьютере - не работает. Поэтому позвольте мне посоветовать использовать 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 вместо простого текста для гибкости и повышения производительности.

...