2013-07-16 11 views
21

Używam PostgreSQL i teraz migruję do MySQL.Konwersja SELECT DISTINCT na zapytania z Postgresql na MySQL

W moich zapytaniach używam PostgreSQL „s SELECT DISTINCT ON (col1, col2, col3), zastanawiałem się, czy istnieje odpowiednik tego oświadczenia w MySQL.

+0

Możesz wypróbować 'Wybierz DISTINCT concat (col1, col2, col3) z tabeli' jeśli potrzebujesz kombinacji trzech do odróżnienia –

+1

Myślę, że w MySQL musisz użyć "częściowego" 'group by' on te trzy kolumny (które nie byłyby dozwolone w żadnym innym DBMS) i żyją z tym, że otrzymujesz nieprzewidywalne wartości dla nierozróżnialnych kolumn. –

Odpowiedz

26

Nie ma dokładnej e quivalent, aby przekonwertować zapytanie PostgreSQL, które używa SELECT DISTINCT ON do MySQL.

Postgresql SELECT DISTINCT ON

w PostgreSQL, następujące zapytanie wyeliminuje wszystkie wiersze gdzie wyrażenia (col1, col2, col3) mecz, i to będzie na bieżąco tylko „pierwszą Col4, Col5 wiersz” dla każdego zestawu dopasowanych wierszy:

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

Więc jeśli stół jest tak:

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

nasz q uery zachowa tylko jeden wiersz dla (1,2,3) i jeden wiersz dla (3,3,3).Powstałe wiersze będzie wtedy:

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

proszę zauważyć, że „pierwszym rzędzie” z każdego zestawu jest nieprzewidywalny, nasza pięść rząd może być (888, 999), a także chyba że określić Zamówienia:

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

(DISTINCT w wyrażeniach musi być zgodny z wyrażeniami znajdującymi się najdalej z lewej ORDER BY, ale ORDER BY może zawierać dodatkowe wyrażenia).

MySQL rozszerzenie GROUP BY

MySQL rozszerza stosowanie GROUP BY tak, że możemy wybrać nonaggregated nie nazwanych kolumn w klauzuli GROUP BY. Za każdym razem, gdy wybieramy nieagregowane kolumny, serwer może wybrać dowolną wartość z każdej grupy z tej kolumny, więc wynikowe wartości będą nieokreślone.

zatem zapytanie Postgresql:

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

można uznać za równoważne tej zapytania mysql

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

zarówno PostgreSQL MySQL zwrotu "Pierwszy wiersz" dla każdego elementu (COL1, col2, col3), aw obu przypadkach zwracany wiersz jest nieprzewidywalny, ponieważ nie określono ani nie zamawiamy klauzuli.

Wiele osób byłoby bardzo skłonny do przekształcenia tej kwerendy PostgreSQL z ORDER BY:

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

z tym jednym:

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

Chodzi o to, aby zastosować ORDER BY podzapytanie tak, że gdy grupy MySQL przez col1, col2, col3 zachowają pierwszą napotkaną wartość dla col4 i col5. Pomysł jest dobry, ale jest błędny! MySQL może dowolnie wybierać dowolne wartości dla col4 i col5, a nie wiemy, jakie są pierwsze napotkane wartości, zależy to od optymalizatora. Więc poprawiłbym to do tego:

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 

, ale to zaczyna być bardziej skomplikowane.

Wnioski

Zgodnie z ogólną zasadą, nie jest dokładny sposób przekonwertować kwerendy PostgreSQL kwerendy MySQL, ale istnieje wiele obejścia, uzyskany kwerendy może być tak proste, jak oryginalne lub może stać się bardzo skomplikowany, ale zależy to od samego zapytania.

-4

należy migrować do PDO lub MSYQLI zamiast MYSQL jak jej już przestarzała.

o swoje pytanie można zrobić

SELECT DISTINCT col1, col2, col3 

lub

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

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

Podoba mi się twoje zdanie: "* MYSQL jest już przestarzałe *";) –

+2

@a_horse_with_no_name ja też kocham twój komentarz :) –

+0

@a_horse Chociaż też to lubię, nie jestem pewien co to dokładnie oznacza. Również nie widzę jak '' PDO' lub 'mysqli' zastępuje postgresql lub inne dbms, ponieważ są to tylko interfejsy. Myślę, że to tylko złe sformułowanie. –

-2

Nie można wybrać różne wartości z wielu kolumn. przy wyborze użyj zapytania jak to

select distinct col1, col2 from table 
-1

pomocą podzapytania w celu ustalenia kolejności i zewnętrzną zapytanie do grupy im.

Jak wskazuje @a_horse_with_no_name, działa to, ponieważ MySQL pozwala na częściową group by, w przeciwieństwie do innych DBMS.

Na przykład:

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

zapytań dla każdego klienta pierwszej kolejności:

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

Wynik:

| 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