2013-07-16 78 views
21

我一直在使用PostgreSQL現在正在遷移到MySQL將SELECT DISTINCT ON查詢從Postgresql轉換爲MySQL

在我的疑問,我使用PostgreSQL的SELECT DISTINCT ON (col1, col2, col3),我不知道是否有在MySQL的本聲明的任何對手。

+0

你可以嘗試 '從表'中選擇DISTINCT concat(col1,col2,col3)'如果你需要這三者的組合是不同的 –

+1

我想在MySQL中你需要使用一個「部分」那三列(這在任何其他數據庫管理系統中都是不允許的),並且存在這樣一個事實,即對於非明顯的列,您將獲得不可預知的值。 –

回答

26

這裏沒有一個確切的è有效地將使用SELECT DISTINCT ON的Postgresql查詢轉換爲MySQL。

PostgreSQL的SELECT DISTINCT ON

在PostgreSQL,下面的查詢將消除所有行表達(col1, col2, col3)比賽,這將只保留「第一COL4,COL5行」爲每組匹配的行:

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

所以,如果你的表是這樣的:

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

我們q uery將只保留一行(1,2,3)和一行(3,3,3)。然後將得到的行會:

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

請注意每個組的「第一行」是不可預測的,我們的拳頭行可能是(888,999),以及除非我們指定一個ORDER BY:

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

(對錶達式的DISTINCT必須匹配最左邊的ORDER BY表達式,但ORDER BY可以包含其他表達式)。

MySQL擴展到GROUP BY

MySQL的擴展使用GROUP BY,使我們可以選擇要在GROUP BY子句中未命名的非聚合列。每當我們選擇nonaggregated列時,服務器可以自由選擇該列中每個組的任何值,因此結果值將是不確定的。

所以這PostgreSQL的查詢:

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

可以被認爲等同於這個MySQL查詢:

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

兩個PostgreSQL和MySQL將返回 「第一排」 每個(COL1,COL2, col3),並且在這兩種情況下,返回的行都是不可預知的,因爲我們沒有指定和按子句排序。

很多人會很誘惑,這PostgreSQL的查詢與ORDER轉換BY:

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

這一個:

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

在這裏的想法是應用ORDER BY來一個子查詢,這樣當MySQL按col1,col2,col3分組時,它將保持col4和col5的第一個遇到的值。 這個想法很好,但它是錯誤的! MySQL可以自由選擇col4和col5的任何值,我們不知道哪些是遇到的第一個值,它取決於優化器。所以我會糾正它:

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 

但這開始變得更加複雜。

結論

作爲一般規則,有沒有到PostgreSQL的查詢轉換爲MySQL查詢的具體的方式,但也有很多解決方法,生成的查詢可能會和原來的一樣簡單或者它可能變得非常複雜,但它取決於查詢本身。

-4

您應該遷移到PDOMSYQLI代替MYSQL其已經過時。

關於你的問題,你可以做

SELECT DISTINCT col1, col2, col3 

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

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

我喜歡你的聲明:「* MYSQL已被棄用*」;) –

+2

@a_horse_with_no_name我也喜歡你的評論:) –

+0

@a_horse雖然我也喜歡它,但我不確定它究竟是什麼意思。我也看不出'PDO'或'mysqli'如何代替postgresql或任何其他dbms,因爲它們只是接口。我想這只是一個錯誤的措辭。 –

-2

不能從多個列中選擇不同的值。同時選擇這樣

select distinct col1, col2 from table 
-1

使用查詢中使用的子查詢,以確定的順序,和一個外部查詢到他們組。

就像@a_horse_with_no_name指出的那樣,這是有效的,因爲MySQL允許部分group by,與其他DBMS不同。

例如:

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

查詢針對每個客戶的一階:

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

結果:

| 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