私はPostgreSQLを使用しており、現在MySQLに移行しています。
私のクエリではPostgreSQLのSELECT DISTINCT ON (col1, col2, col3)
を使用していますが、このステートメントに対応するものがMySQLにあるかどうか疑問に思っていました。
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
このクエリでは、(1,2,3)の1行と(3,3,3)の1行のみが保持されます。結果の行は次のようになります。
col4 | col5
-----------
777 | 888
555 | 555
各セットの「最初の行」は予測できないことに注意してください。ORDERBYを指定しない限り、最初の行も(888、999)になる可能性があります。
SELECT DISTINCT ON (col1, col2, col3) col4, col5
FROM tablename
ORDER BY col1, col2, col3, col4
(式のDISTINCTは左端のORDER BY式と一致する必要がありますが、ORDER BYには追加の式を含めることができます)。
MySQL SQLのGROUP BYへの拡張
MySQLは GROUP BY の使用を拡張して、GROUP BY句で指定されていない非集約列を選択できるようにします。集計されていない列を選択するときはいつでも、サーバーはその列から各グループから任意の値を自由に選択できるため、結果の値は不確定になります。
したがって、この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)の「最初の行」を返します。句を指定していないため、どちらの場合も返される行は予測できません。
多くの人は、ORDER BYを使用してこのPostgresqlクエリを変換することに非常に魅力的です。
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クエリに変換する正確な方法はありませんが、多くの回避策があります。結果のクエリは元のクエリと同じくらい単純になるか、非常に複雑になる可能性がありますが、クエリ自体。
サブクエリを使用して順序を決定し、外部クエリを使用してそれらをグループ化します。
@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 |