2013-07-16 7 views
21

Sto usando PostgreSQL e ora la migrazione a MySQL.Conversione di SELECT DISTINCT su query da Postgresql a MySQL

In mie domande, sto usando PostgreSQL s' SELECT DISTINCT ON (col1, col2, col3), mi chiedevo se non v'è alcuna contropartita di questa affermazione in MySQL.

+0

Si può provare 'Selezionare DISTINCT concat (col1, col2, col3) dalla tabella' se è necessario la combinazione dei tre per essere distinti –

+1

Immagino che in MySQL sia necessario utilizzare un "partial" 'group by' on quelle tre colonne (che non sarebbero consentite in nessun altro DBMS) e convivono con il fatto che si ottengono valori imprevedibili per le colonne non distinte. –

risposta

26

Non c'è un esatto e quivalente per convertire una query Postgresql che utilizza SELECT DISTINCT ON su MySQL.

Postgresql SELEZIONA distinti su

in PostgreSQL, la seguente query eliminerà tutte le righe in cui le espressioni (col1, col2, col3) partita, e manterrà solo la "prima col4, fila Col5" per ogni set di righe abbinate:

SELECT DISTINCT ON (col1, col2, col3) col4, col5 
FROM tablename 

Così, se il tavolo è come questo:

col1 | col2 | col3 | col4 | col5 
-------------------------------- 
1 | 2 | 3 | 777 | 888 
1 | 2 | 3 | 888 | 999 
3 | 3 | 3 | 555 | 555 

nostro q manterrà solo una riga per (1,2,3) e una riga per (3,3,3).Le righe risultanti saranno quindi:

col4 | col5 
----------- 
777 | 888 
555 | 555 

prega di notare che la "prima fila" di ogni set è imprevedibile, la nostra fila pugno potrebbe essere (888, 999), così a meno che non specifichiamo un ORDER BY:

SELECT DISTINCT ON (col1, col2, col3) col4, col5 
FROM tablename 
ORDER BY col1, col2, col3, col4 

(il DISTINCT sulle espressioni deve corrispondere alle espressioni ORDER BY più a sinistra, ma l'ORDER BY può contenere espressioni aggiuntive).

MySQL estensione a GROUP BY

MySQL estende l'uso di GROUP BY in modo da poter selezionare le colonne nonaggregated non nominate nella clausola GROUP BY. Ogni volta che selezioniamo colonne non aggregate, il server è libero di scegliere qualsiasi valore da ciascun gruppo da quella colonna, quindi i valori risultanti saranno indeterminati.

Quindi questa query PostgreSQL:

SELECT DISTINCT ON (col1, col2, col3) col4, col5 
FROM tablename 

può essere considerato equivalente a questa query MySQL:

SELECT col4, col5 
FROM tablename 
GROUP BY col1, col2, col3 

sia PostgreSQL e MySQL restituirà la "prima fila" per ogni (col1, col2, col3), e in entrambi i casi la riga restituita è imprevedibile perché non abbiamo specificato e ordine per clausola.

Un sacco di gente sarebbe molto tentato di convertire questa query PostgreSQL con un'ORDER BY:

SELECT DISTINCT ON (col1, col2, col3) col4, col5 
FROM tablename 
ORDER BY col1, col2, col3, col4 

con questo:

SELECT col4, col5 
FROM (
    SELECT col1, col2, col3, col4, col5 
    FROM tablename 
    ORDER BY col1, col2, col3, col4 
) s 
GROUP BY col1, col2, col3 

l'idea è quella di applicare un ORDER BY per una subquery in modo tale che quando MySQL raggruppa col1, col2, col3 manterrà il primo valore incontrato per col4 e col5. L'idea è buona, ma è sbagliata! MySQL è libero di scegliere qualsiasi valore per col4 e col5 e non sappiamo quali siano i primi valori rilevati, dipende dall'ottimizzatore. Quindi lo correggo a questo:

SELECT t1.col4, t1.col5 
FROM tablename t1 INNER JOIN (SELECT col1, col2, col3, MIN(col4) as m_col4 
           FROM tablename 
           GROUP BY col1, col2, col3) s 
    ON t1.col1=s.col1 
     AND t1.col2=s.col2 
     AND t1.col3=s.col3 
     AND t1.col4=s.m_col4 
GROUP BY 
    t1.col1, t1.col2, t1.col3, t1.col4 

ma questo sta iniziando a diventare più complicato.

Conclusione

Come regola generale, non c'è un modo esatto per convertire una query PostgreSQL a una query MySQL, ma ci sono un sacco di soluzioni alternative, la query risultante potrebbe essere semplice come quello originale o potrebbe diventare molto complicato, ma dipende dalla query stessa.

-4

si dovrebbe migrare verso DOP o MSYQLI invece di MYSQL come già deprecato.

sulla tua domanda si può fare

SELECT DISTINCT col1, col2, col3 

o

SELECT col1, col2, col3 
    ........ 

    GROUP BY col1 --//--- or whatever column you want to be distinct 
+3

Mi piace la tua affermazione: "* MYSQL è già deprecato *";) –

+2

@a_horse_with_no_name anche io amo il tuo commento :) –

+0

@a_horse Anche se mi piace anche io non sono sicuro di cosa significhi esattamente. Inoltre non vedo come 'PDO' o' mysqli' sostituiscano postgresql o qualsiasi altro dbms in quanto sono solo interfacce. Immagino sia solo una brutta formulazione. –

-2

Non è possibile selezionare valori distinti da più colonne. mentre si seleziona interrogazione uso simili

select distinct col1, col2 from table 
-1

Utilizzare una sottoquery per determinare l'ordine, e una query esterna raggrupparli.

Come @a_horse_with_nome_non punta, questo funziona perché MySQL consente parziale group by, a differenza di altri DBMS.

Ad esempio:

CREATE TABLE customer_order 
    (`customer` varchar(5), `item` varchar(6), `date` datetime) 
; 

INSERT INTO customer_order 
    (`customer`, `item`, `date`) 
VALUES 
    ('alice', 'widget', '2000-01-05 00:00:00'), 
    ('bob', 'widget', '2000-01-02 00:00:00'), 
    ('alice', 'widget', '2000-01-01 00:00:00'), 
    ('alice', 'wodget', '2000-01-06 00:00:00') 
; 

query per il primo ordine di ogni cliente:

select * 
from 
    (select customer, item, date 
    from customer_order 
    order by date) c 
group by customer 

Risultato:

| CUSTOMER | ITEM |       DATE | 
|----------|--------|--------------------------------| 
| alice | widget | January, 01 2000 00:00:00+0000 | 
|  bob | widget | January, 02 2000 00:00:00+0000 | 

http://sqlfiddle.com/#!2/6cbbe/1