DISTINCT
がどのように機能するかは理解していますが、DISTINCT ON (expression)
は理解していません。
このスクリーンショットの最初の例を見てください。
(a % 2)
一部はすべてに影響しますか? a % 2
はtrueと評価され、それを返し、他のすべてのタプルについてもそうし続けますが、戻り値が異なる場合にのみ戻りますか?
前の答えは正しいように見えますが、特に明確だとは思いません。
PostGreSQLの 公式ドキュメント のスニペットは次のとおりです...
DISTINCT ON(式[、...])は、指定された式が等しいと評価される行の各セットの最初の行のみを保持します。 [...] ORDER BYを使用して目的の行が最初に表示されるようにしない限り、各セットの「最初の行」は予測できないことに注意してください。 [...] DISTINCT ON式は、左端のORDERBY式と一致する必要があります。
最初のポイントは、ON ()
に入れたものはすべて、_ORDER BY
_の最初に来る必要があるということです。理由は、すぐに明らかになることを願っています...
_SELECT DISTINCT ON (a) a, b, c FROM a_table ORDER BY a, b
_
次に、結果がフィルタリングされるため、個別のエンティティごとに、最初の行のみが実際に返されます。
例えば...
_CREATE TABLE example (
id INT,
person_id INT,
address_id INT,
effective_date DATE
);
INSERT INTO
example (id, person_id, address_id, effective_date)
VALUES
(1, 2, 1, '2000-01-01'), -- Moved to first house
(5, 2, 2, '2004-08-19'), -- Went to uni
(9, 2, 1, '2007-06-12'), -- Moved back home
(2, 4, 3, '2007-05-18'), -- Moved to first house
(3, 4, 4, '2016-02-09') -- Moved to new house
;
SELECT DISTINCT ON (person_id)
*
FROM
example
ORDER BY
person_id,
effective_date DESC
;
_
これにより、各人のすべてのレコードが連続するように結果が並べ替えられ、最新のレコードから古いレコードの順に並べられます。次に、各人について、最初のレコードが返されます。したがって、各人の最新の住所を指定します。
_Step 1 : Apply the ORDER BY...
id | person_id | address_id | effective_date
----+-----------+------------+----------------
9 | 2 | 1 | '2007-06-12'
5 | 2 | 2 | '2004-08-19'
1 | 2 | 1 | '2000-01-01'
3 | 4 | 4 | '2016-02-09'
2 | 4 | 3 | '2007-05-18'
Step 2 : filter to just the first row per person_id
id | person_id | address_id | effective_date
----+-----------+------------+----------------
9 | 2 | 1 | '2007-06-12'
3 | 4 | 4 | '2016-02-09'
_
これは、以下とほぼ同等です...
_SELECT
*
FROM
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY person_id
ORDER BY effective_date DESC) AS person_address_ordinal
FROM
example
)
AS sorted_example
WHERE
person_address_ordinal = 1
_
_(a % 2)
_が何をするかについての質問に関しては、それはMOD(a, 2)
の単なる数学計算なので、次のことができます...
_CREATE TABLE example (
id INT,
score INT
);
INSERT INTO
example (id, score)
VALUES
(1, 2),
(2, 6),
(3, 5),
(4, 3),
(5, 4),
;
SELECT DISTINCT ON (id % 2)
*
FROM
example
ORDER BY
id % 2,
score DESC
;
_
これにより、偶数のid
s(_id % 2
_は_0
_)に最高のスコアが与えられ、次に最高のスコアは奇数のid
s(ここで、_id % 2
_は_1
_)と同じです。
_Step 1 : Apply the ORDER BY...
id | score
----+-------
2 | 6 -- id % 2 = 0
4 | 3 -- id % 2 = 0
3 | 5 -- id % 2 = 1
5 | 4 -- id % 2 = 1
1 | 2 -- id % 2 = 1
Step 2 : filter to just the first row per `id % 2`
id | score
----+-------
2 | 6 -- id % 2 = 0
3 | 5 -- id % 2 = 1
_
%2はモジュロ演算子です。 0または1しか取得できません(列がNULL可能の場合はNULL
)。
例えば:
i | a | a%2
1 10 0
2 11 1
3 12 0
4 13 0
コード:
CREATE TABLE r(i INT, a INT);
INSERT INTO r(i, a) VALUES (1,10), (2,11),(3,12),(4,13);
SELECT DISTINCT ON (a%2) a
FROM r;
出力:
10
11
SELECT DISTINCT ON (a%2) a
FROM r
ORDER BY a%2,i DESC;
出力:
12
13