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).

CHRIS
fonte
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');
Clive
fonte
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:

TBI Infotech
fonte
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');
Scott Joudry
fonte
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();
priyank
fonte
11
A função distinta recebe um booleano como argumento, não uma string.
Felix Eve