Come db_select DISTINCT su un campo particolare in Drupal 7?


7

Comprendo che è possibile specificare -> distinct () sull'istruzione db_select in modo che restituisca valori distinti solo quando si guardano TUTTI i campi. Ma quello che voglio è restituire valori distinti guardando solo UN campo. Ecco il mio codice:

$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');

Supponiamo che io voglia che la colonna distinta sia e.nid. Penseresti che -> distinguibile ('e.nid') funzionerebbe ma restituisce comunque valori distinti in base a tutti i campi (ovvero distinti (colonne1, colonna2, colonna3, ecc.).


1
Qualche possibilità che potresti dare a un campione dell'output SQL che stai cercando? Ciò renderebbe abbastanza facile capire come convincere db_selecta fare lo stesso
Clive

Risposte:


12

Supponendo che stai cercando di arrivare a circa questa query:

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

Dovresti usare:

$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');

Questo mi dà tutti i campi distinti, non solo nid essendo distinti
CHRIS

Non sono sicuro di cosa intendi, quanto sopra è una query distinta ... quale SQL stai cercando di produrre?
Clive

1
supponiamo che ci sia '4' '4' '5' '5' nella colonna nid con una colonna corrispondente chiamata 'type' con 'a' 'b' 'c' 'd'. bene, se seleziono distinto su entrambe le colonne (nid, tipo), il risultato avrà 4 righe. ma se seleziono distinto su JUST nid, il risultato avrà 2 righe. Sto provando a selezionare distinto su JUST nid
CHRIS il

2
Penso che tu abbia frainteso il funzionamento del raggruppamento in SQL ... per fare ciò che stai descrivendo avresti bisogno di rimuovere la colonna del tipo dai campi selezionati
Clive

7

DISTINCT è in realtà un post-modificatore globale per SELECT, ovvero, a differenza di SELECT ALL (che restituisce tutte le risposte) è SELECT DISTINCT (che restituisce tutte le risposte uniche). Quindi un singolo DISTINCT agisce su TUTTE le colonne che gli dai.

Questo rende davvero difficile usare DISTINCT su una singola colonna, mentre si ottengono le altre colonne, senza fare grandi backflips estremamente brutti.

La risposta corretta è utilizzare un GROUP BY sulle colonne in cui si desidera avere risposte univoche:


Esattamente. Ecco perché DBTNG lo ha a livello di query. L'unica volta che DISTINCT è a livello di colonna (o sembra vagamente simile) è quando lo fai COUNT(DISTINCT foo)ma anche in questo caso è un modificatore della funzione aggregatore.

2

Rimuovere ->distinct()e sostituirlo con$event_table->AddExpression('distinct e.nid', 'nid');

Così:

$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]: errore di sintassi o violazione di accesso: 1064 Si è verificato un errore nella sintassi SQL; controlla il manuale corrispondente alla versione del tuo server MySQL per la sintassi corretta da usare vicino a 'distinto e.nid AS nid DA mcc_notify_event_queue e nodo INNER JOIN n ON e.nid' alla riga 1: SELECT e. *, n. tipo AS , n. stato AS stato, n. titolo AS titolo, distinto e.nid AS anid DA {mcc_notify_event_queue} e INNER JOIN {node} n ON e.nid = n.nid GROUP BY e.time ORDER BY e.time ASC; Array ()
CHRIS,

non può usare e. * e e.nid distinto, genera un errore. Dovrai scrivere i tuoi campi come ho notato sopra.
Scott Joudry,

Ricevo ancora un errore. Tutto quello che ho fatto è cambiare il codice in $ event_table-> fields ('e', array ('nid', 'time', 'event_type')) // SELEZIONARE i campi dagli eventi
CHRIS,

stai ancora selezionando nid due volte in quel caso che spiega l'errore. Prova $ event_table-> fields ('e', array ('time', 'event_type'))
Scott Joudry,

ancora un errore distinto e.nid AS nid FROM my_module_event_queue e nodo INNER JOIN n ON e.nid 'alla riga 1: SELECT e.time AS time, e.event_type AS event_type, n.type AS type, n.status AS status, n. titolo AS, distinto e.nid AS nid DA {my_module_event_queue} e INNER JOIN {node} n ON e.nid = n.nid GROUP BY e.time ORDER BY e.time ASC;
CHRIS,

-1

Se si utilizza questa query, viene fornita una query distinta corretta.

<?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();

1
La funzione distinta assume un valore booleano in quanto argomento, non una stringa.
Felix Eve,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.