Während die vorherige Antwort richtig erscheint, fühle ich nicht, dass es besonders klar ist.
Die Schnipsel aus dem Official documentation für PostGreSQL ist wie folgt ...
DISTINCT ON (expression [...]) hält nur die erste Zeile eines jeden Satzes von Zeilen, in denen die angegebenen Ausdrücke zu bewerten, gleich. [...] Beachten Sie, dass die "erste Zeile" jedes Satzes unvorhersehbar ist, es sei denn, ORDER BY wird verwendet, um sicherzustellen, dass die gewünschte Zeile zuerst angezeigt wird. [...] Die DISTINCT ON-Ausdrücke müssen mit den äußersten ORDER BY-Ausdrücken übereinstimmen.
Der erste Punkt ist, dass alles, was Sie in der ON()
setzen, muss zunächst in der der ORDER BY
aus Gründen kommen, die hoffentlich in Kürze klar werden wird ...
SELECT DISTINCT ON (a) a, b, c FROM a_table ORDER BY a, b
Die Ergebnisse dann gefiltert werden, so dass für jede der verschiedenen Entitäten nur die erste Zeile zurückgegeben wird.
Zum Beispiel ...
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
;
Dies wird die Ergebnisse der Reihenfolge, so dass alle Datensätze für jede Person zusammenhängen, von den jüngsten Datensatz zur ältesten bestellt. Dann wird für jede Person der erste Datensatz zurückgegeben. So geben Sie die letzte Adresse für jede Person an.
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'
Es ist im Großen und Ganzen entspricht dies folgenden ...
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
Was die Frage, was (a % 2)
tut, es ist nur eine mathematische Berechnung für MOD(a, 2)
, so könnten Sie folgendes tun ...
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
;
, die die höchste Punktzahl für die sogar id
s geben würde (wo id % 2
gleich 0
), dann die höchste Punktzahl der ungeraden id
s (wo id % 2
gleich 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