2016-01-09 19 views
7

Sembra che nella versione 5.7 di MySQL, hanno aggiunto una cosa brutta che era (o è ancora) un vero headache per coloro che si occupano di SQL Server.SELECT DISTINCT e ORDER BY in MySQL

Il fatto è: MySQL genera un errore, quando si tenta di SELECT DISTINCT righe per un set di colonne e si desidera ORDER BY un altro insieme di colonne. In precedenza, nella versione 5.6 e persino in alcune versioni della versione 5.7, si poteva fare ciò, ma ora è proibito (almeno per impostazione predefinita).

Spero che esista qualche configurazione, alcune variabili che potremmo impostare per farlo funzionare. Ma sfortunatamente non conosco quella brutta variabile. Spero che qualcuno lo sappia.

EDIT

Questa è una domanda tipica nel mio caso che ha lavorato letteralmente per anni (fino a quando l'ultima build di MySQL 5.7):

SELECT DISTINCT a.attr_one, a.attr_two, a.attr_three, b.attr_four FROM table_one a 
LEFT JOIN table_two b ON b.some_idx = a.idx 
ORDER BY b.id_order 

E, in effetti, se ora includo b.id_order alla parte SELECT (come suggerisce MySQL), quindi quello che otterrò, sarà spazzatura.

+0

È questo la query effettiva? – Strawberry

+0

Sì, è una query del mondo reale. – Jacobian

risposta

7

Nella maggior parte dei casi, una clausola DISTINCT può essere considerata come un caso speciale di GROUP BY. Ad esempio,

ONLY_FULL_GROUP_BY

MySQL 5.7.5 e fino implementa il rilevamento della dipendenza funzionale. Se la modalità SQL ONLY_FULL_GROUP_BY è abilitata (che è predefinita), MySQL rifiuta le query per le quali l'elenco di selezione, condizione HAVING o ORDER BY fa riferimento a colonne non aggregate che non sono né denominate nella clausola GROUP BY né dipendono dal punto di vista funzionale su di essi. (Prima 5.7.5, MySQL non rileva dipendenza funzionale e ONLY_FULL_GROUP_BY non è abilitato di default. Per una descrizione di pre-5.7.5 comportamento)

Se ONLY_FULL_GROUP_BY è disattivato, un'estensione MySQL all'uso standard SQL di GROUP BY consente l'elenco di selezione, la condizione HAVING o l'elenco ORDER BY per fare riferimento a colonne non aggregate anche se le colonne non dipendono funzionalmente dalle colonne GROUP BY. Ciò fa sì che MySQL accetti la query precedente. In questo caso, il server è libero di scegliere qualsiasi valore da ciascun gruppo, quindi a meno che non siano gli stessi, i valori scelti sono indeterminati, il che probabilmente non è ciò che si desidera. Inoltre, la selezione dei valori di ciascun gruppo non può essere influenzata dall'aggiunta di una clausola ORDER BY. L'ordinamento dei set di risultati si verifica dopo aver scelto i valori e ORDER BY non influisce sul valore all'interno di ciascun gruppo selezionato dal server. La disabilitazione di ONLY_FULL_GROUP_BY è utile soprattutto quando si sa che, a causa di alcune proprietà dei dati, tutti i valori in ogni colonna non aggregata non denominata in GROUP BY sono uguali per ciascun gruppo.

per più http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_only_full_group_by

per particolare risposta

SELECT DISTINCT attr_one, 
      attr_two, 
      attr_three, 
      attr_four 
FROM 
    (SELECT a.attr_one, 
     a.attr_two, 
     a.attr_three, 
     b.attr_four 
    FROM table_one a 
    LEFT JOIN table_two b ON b.some_idx = a.idx 
    ORDER BY b.id_order) tmp 
+2

Lo so. Ho già disabilitato 'ONLY_FULL_GROUP_BY' impostando' sql_mode' in '" "' in 'my.cnf', ma questo stesso problema con' DISTINCT' e 'ORDER BY' non è risolto da questo. – Jacobian

+0

Qual è la tua versione di sql, hai provato max_sort_length? – developerCK

+0

La versione è 5.7.10. Cosa intendi provando questa variabile? – Jacobian

0

Ho letto il post sul link che hai menzionato, e sembra che sia stata data la chiara spiegazione del motivo per cui l'errore è stato generato e come evitarlo.

Nel tuo caso si consiglia di provare quanto segue (non testato ovviamente):

SELECT a.attr_one, a.attr_two, a.attr_three, b.attr_four 
FROM table_one a 
LEFT JOIN table_two b ON b.some_idx = a.idx 
GROUP BY a.attr_one, a.attr_two, a.attr_three, b.attr_four 
ORDER BY max(b.id_order) 

Si consiglia di scegliere se utilizzare ORDER BY max(b.id_order) o ORDER BY min(b.id_order) o altra funzione di aggregazione

+0

Non funzionerà in MySQL. Se non mi sbaglio in MySQL, non vi è alcuna garanzia che il set di risultati sia il primo 'ORDER'ed e dopo' GROUP'ed 'BY'. – Jacobian

+0

Oppure, come dichiarato da developerCK, "Inoltre, la selezione dei valori di ciascun gruppo non può essere influenzata dall'aggiunta di una clausola ORDER BY. L'ordinamento dei set di risultati si verifica dopo aver scelto i valori e ORDER BY non influenza il valore all'interno di ciascun gruppo del server sceglie. " – Jacobian