Como obter valores exclusivos da tabela de dados usando DQL?
Pergunta
Estou tendo uma tabela na qual existe uma coluna na qual vários valores são armazenados. Desejo recuperar valores exclusivos dessa tabela usando DQL.
Doctrine_Query::create()
->select('rec.school')
->from('Records rec')
->where("rec.city='$city' ")
->execute();
Agora eu quero apenas valores únicos. Alguém pode me dizer como fazer isso ...
Editar
Estrutura da tabela:
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 ;
Esta é a consulta que estou usando:
Doctrine_Query::create()
->select('DISTINCT rec.city')
->from('Records rec')
->where("rec.state = '$state'")
// ->getSql();
->execute();
Gerando SQL para isso me dá:
SELECT DISTINCT r.id AS r__id, r.city AS r__city FROM records r WHERE r.state = 'AR'
Agora verifique o SQL gerado :::: Distinto está na coluna 'ID', onde eu quero distinto na coluna da cidade. Alguém sabe como consertar isso.
Edit2
O ID é único porque é um valor incremental automático.YA Eu tenho algumas duplicatas reais na coluna da cidade como: Delhi e Delhi. Bem .. agora quando estou tentando buscar dados, estou recebendo Delhi duas vezes. Como posso fazer uma consulta assim:
select DISTINCT rec.city where state="xyz";
Porque isso me dará a saída adequada.
Edit3:
Alguém que pode me dizer como descobrir esta consulta .. ???
Solução
Depende de qual versão você está usando, mas eu tive o mesmo problema e -> distint () funcionou para mim.
Doctrine_Query::create()
->select('rec.city')->distinct()
->from('Records rec')
->where("rec.state = '$state'")
->execute();
Outras dicas
Depois de mais algumas pesquisas e experimentais, percebi. Não encontrei nenhuma documentação para DD '13, mas encontrei alguns para DD '10, que foi "perto o suficiente" para traduzir para a versão mais recente. Aqui estão algumas páginas do MS Doc relevantes:
passo a passo: calcular pontuações normalizadas para kpis
configure as propriedades da coluna de dados < BR>
configure Configurações de tempo e agregação
Para o meu problema específico, aqui estão as etapas que tirei:
tabela SQL
& # 8226; Altere a coluna PassFail de um bit para um inteiro que contenha 0 ou 100 (em vez de 0 ou 1).
fonte de dados
• Na guia view , defina todos os campos (diferentes dos campos do CreateDate e PassFail) para um tipo de coluna de Ignore (isso é no detalhes Painel).
• Para o campo do criado, defina o tipo de coluna a ser timedimension . Para o campo PassFail, defina o tipo de coluna para fato e a agregação para média .
kpi
• Redefina o formato número para real e destino para (padrão) .
• Altere o mapeamento de dados de destino de 1 a 100 (valor ainda fixo).
• Na coluna de cálculo,
Isso deve fazer isso! Agora, para filtros ...
Não há necessidade no Rawsql
Em lugar de -> selecione ('Rec.city distinto')
Use -> Selecione ('distinto (rec.city) como cidade')
Você pode usar o RAW_SQL classe para conseguir isso. Aqui está um teste que acabei de fazer no meu próprio banco de dados:
<?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";
}
?>
Distinto é uma função de agregação. Como tal, a doutrina não pode hidratar seu resultado em objetos. Use uma estratégia de hidratação diferente, como Bartman sugeriu.
$q = Doctrine_Query::create()
->select('DISTINCT rec.city')
->from('Records rec')
->execute(array(), Doctrine_Core::HYDRATE_SCALAR);
Funcionou bem para mim
O motivo pelo qual a doutrina está sempre adicionando a chave primária à lista de campos está dentro da hidratação. Quando a doutrina busca linhas do banco de dados, ele hidrata (= converte) em uma hierarquia de objetos e faz referência aos objetos do modelo usando a chave primária. No seu caso, esse comportamento não é procurado, pois apenas os nomes da cidade são de interesse.
Sugiro duas soluções, infelizmente não posso testá -las agora.
- Tente usar Doutrina_rawsql. O RawSQL possui um manuseio especial para consultas distintas.
$q = Doctrine_RawSql::create()
->select('DISTINCT {rec.city}')
->from('Records rec')
->where('rec.state = ?', $state)
->addComponent('rec', 'Record');
$cities = $q->execute()
- Use um hidrator baseado em hierarquia não objeto-objeto. Isso pode impedir a doutrina de buscar o campo principal da chave para inicializar a classe Model. Consulte a documentação (não é possível postar o link - novo usuário. Desculpe.) Para obter mais informações.
$q = Doctrine_Query::create()
->select('DISTINCT rec.city')
->from('Records rec')
->where("rec.state = ?", $state);
$cities = $q->execute(array(), Doctrine_Core::HYDRATE_SCALAR);
$ cidades devem conter uma matriz de matrizes com chaves como 'rec_city'.
Observe o uso do ?
Armazenante nas declarações onde, é uma boa prática permitir que a doutrina escape e não lute com ela mesmo.
$query = $this->getEntityManager()->createQueryBuilder()
->select('DISTINCT(p.document)')
->from('Products', 'p');
Este funciona para mim.
Respondeu novamente:
Verifiquei isso no meu computador local - não funcionou. Então, deixe -me aconselhar para usar o PDO até que isso seja aprimorado ou corrigido:
$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();
Dica
Eu recomendo que você use Chave estrangeira referenciado à lista de cidades em city
coluna em vez de texto simples para flexibilidade e melhor desempenho.