Como db_select DISTINCT em um campo específico no Drupal 7?


7

Entendo que você pode especificar -> distinct () na instrução db_select para que ele retorne apenas valores distintos ao examinar TODOS os campos. Mas o que eu quero é retornar valores distintos apenas olhando para UM campo. Aqui está o meu código:

$event_table = db_select('my_table', 'e')
    ->distinct()
    ->orderBy('e.time', 'ASC');//ORDER BY
$event_table->join('node', 'n', 'e.nid = n.nid'); //JOIN node with events
$event_table->groupBy('e.time');//GROUP BY time
$event_table->fields('e')//SELECT the fields from events
    ->fields('n',array('type','status','title'))//SELECT the fields from node
    ->orderBy('e.time', 'ASC');//ORDER BY

$result_event_table = $event_table->execute();
$result_event_table = $result_event_table->fetchAllAssoc('time');

Suponha que eu queira que a coluna distinta seja e.nid. Você pensaria -> distinct ('e.nid') funcionaria, mas ainda retornaria valores distintos com base em todos os campos (ou seja, distintos (colunas1, coluna2, coluna3, etc).


11
Alguma chance de você dar uma amostra da saída SQL que está procurando? Isso tornaria muito fácil descobrir como persuadir db_selecta fazer o mesmo
Clive

Respostas:


12

Supondo que você esteja tentando obter aproximadamente essa consulta:

SELECT DISTINCT e.nid AS nid, e.time AS time, n.type AS type, n.status AS status, n.title AS title
FROM 
{my_table} e
INNER JOIN {node} n ON n.nid = e.nid
GROUP BY e.time
ORDER BY e.time ASC

Você usaria:

$query = db_select('my_table', 'e')
  ->distinct()
  ->fields('e', array('nid', 'time', 'foo', 'bar'))
  ->fields('n', array('type', 'status', 'title'))
  ->groupBy('e.time')
  ->orderBy('e.time');

$query->join('node', 'n', 'n.nid = e.nid');

Isso só me dá todos os campos distintos, não apenas NID ser distinto
CHRIS

Não sei ao certo o que você quer dizer, a pergunta acima é distinta ... qual SQL você está tentando produzir?
Clive

11
suponha que exista '4' '4' '5' '5' na coluna nid com uma coluna correspondente denominada 'type' com 'a' 'b' 'c' 'd'. bem, se eu selecionar distinto nas duas colunas (nid, type), o resultado terá 4 linhas. mas se eu selecionar distinto em APENAS nid, o resultado terá 2 linhas. Eu estou tentando selecionar distintas em apenas nid
CHRIS

2
Eu acho que você está entendendo mal como o agrupamento funciona no SQL ... para fazer o que você está descrevendo, seria necessário remover a coluna de tipo dos campos selecionados
Clive

7

DISTINCT é na verdade um pós-modificador global para SELECT, ou seja, ao contrário de SELECT ALL (retornando todas as respostas), é SELECT DISTINCT (retornando todas as respostas exclusivas). Portanto, um único DISTINCT atua em TODAS as colunas que você fornecer.

Isso torna muito difícil o uso do DISTINCT em uma única coluna, enquanto as outras são obtidas, sem grandes retrocessos extremamente feios.

A resposta correta é usar um GROUP BY nas colunas em que você deseja obter respostas exclusivas:


Exatamente. É por isso que o DBTNG o coloca no nível da consulta. A única vez que DISTINCT é no nível da coluna (ou parece vagamente) é quando você faz isso, COUNT(DISTINCT foo)mas mesmo assim é um modificador da função agregadora.

2

Remova ->distinct()e substitua-o por$event_table->AddExpression('distinct e.nid', 'nid');

Igual a:

$event_table = db_select('my_table', 'e');
$event_table->AddExpression('distinct e.nid', 'nid')
$event_table->orderBy('e.time', 'ASC');//ORDER BY
$event_table->join('node', 'n', 'e.nid = n.nid'); //JOIN node with events
$event_table->groupBy('e.time');//GROUP BY time

// you need to outline all fields here, can't use e.*
$event_table->fields('e')//SELECT the fields from events

    ->fields('n',array('type','status','title'))//SELECT the fields from node
    ->orderBy('e.time', 'ASC');//ORDER BY

$result_event_table = $event_table->execute();
$result_event_table = $result_event_table->fetchAllAssoc('time');

PDOException: SQLSTATE [42000]: Erro de sintaxe ou violação de acesso: 1064 Você possui um erro na sintaxe do SQL; verifique o manual que corresponde à versão do servidor MySQL para a sintaxe correta a ser usada perto de 'e.nid AS.id nid FROM mcc_notify_event_queue e nó INNER JOIN n ON e.nid' na linha 1: SELECT e. *, n.type AS type , n.status AS status, n.title AS title, distinto e.nid AS anid FROM {mcc_notify_event_queue} e INNER JOIN {node} n ON e.nid = n.nid GROUP BY e.time ORDER BY e.time ASC; Matriz ()
CHRIS

não pode usar e. * e e.nid distinto, gera um erro. Você precisará escrever seus campos como observei acima.
21814 Scott Joudry

Ainda estou recebendo um erro. Tudo o que fiz foi alterar seu código para $ event_table-> fields ('e', array ('nid', 'time', 'event_type')) // SELECT os campos dos eventos
CHRIS

você ainda está selecionando nid duas vezes nesse caso, o que explica o erro. Tente $ event_table-> fields ('e', array ('time', 'event_type')))
Scott Joudry

ainda um erro distinto e.nid AS nid FROM my_module_event_queue e INNER JOIN node n ON e.nid 'na linha 1: SELECT e.time AS time, e.event_type AS event_type, n.type AS type, n.status AS status, n.title AS title, e.nid distinto AS nid FROM {my_module_event_queue} e INNER JOIN {node} n ON e.nid = n.nid GRUPO POR e.time ORDER BY e.time ASC;
CHRIS 21/07

-1

Se você usar essa consulta, ela fornecerá uma consulta distinta adequada.

<?php  

$select = db_select('service_payment_transaction','o');
$select->distinct('o.transaction_id');
$select->innerJoin('users', 'u', 'u.uid = o.user_id');
$select->fields('o');
$select->fields('u');
$select->condition('o.service_gv_code','','!=');
$select->range($start,$page_count);
$select->groupBy('o.service_gv_code');
$select->orderBy('transaction_id', 'DESC');
$result_query = $select->execute();

11
A função distinta recebe um booleano como argumento, não uma string.
Felix Eve
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.