3

PostgreSQLに2つのテーブルがあるとしましょう。

表「市民」

country_ref   citizen_name    entry_date
-----------------------------------------------------
0             peter           2013-01-14 21:00:00.000
1             fernando        2013-01-14 20:00:00.000
0             robert          2013-01-14 19:00:00.000
3             albert          2013-01-14 18:00:00.000
2             esther          2013-01-14 17:00:00.000
1             juan            2013-01-14 16:00:00.000
3             egbert          2013-01-14 15:00:00.000
1             francisco       2013-01-14 14:00:00.000
3             adolph          2013-01-14 13:00:00.000
2             emilie          2013-01-14 12:00:00.000
2             jacques         2013-01-14 11:00:00.000
0             david           2013-01-14 10:00:00.000

表「国」

country_id     country_name   country_group
-------------------------------------------
0              england        0
1              spain          0 
2              france         1
3              germany        1

ここで、特定のcountry_groupの各国の「citizens」テーブルに最後に入力された市民を取得したいと思います。

これまでの私の最善の試みはこのクエリです(Query_1と呼びましょう):

SELECT country_ref, MAX(entry_date) FROM citizens 
LEFT JOIN countries ON country_id = country_ref 
WHERE country_group = 1 GROUP BY country_ref

出力:

country_ref   max
---------------------------------
3             2013-01-14 18:00:00
2             2013-01-14 17:00:00

だから私はすることができます:

SELECT citizen_name FROM citizens WHERE (country_ref, entry_date) IN (Query_1)

...これは私が探している出力を私に与えるでしょう:albertそしてesther

しかし、私は単一のクエリでこれを達成したいと思います。可能かしら?

4

3 に答える 3

7

これは最も単純で最速である必要があります。

SELECT DISTINCT ON (i.country_ref)
       i.citizen_name
FROM   citizens  i
JOIN   countries o ON o.country_id = i.country_ref
WHERE  o.country_group = 1
ORDER  BY i.country_ref, i.entry_date DESC

リストに追加するだけで、両方のテーブルからより多くの列を簡単に返すことができますSELECT
SQLフィドル。

この関連する回答の詳細、リンク、および説明:

于 2013-02-11T06:25:08.823 に答える
3
SELECT citizen_name, 
       country_ref, 
       entry_date
from (
  SELECT cit.citizen_name, 
         cit.country_ref, 
         MAX(cit.entry_date) over (partition by cit.country_ref) as max_date,
         cit.entry_date
  FROM citizens cit
    LEFT JOIN countries cou ON cou.country_id = cit.country_ref 
  WHERE cou.country_group = 1 
) t
where max_date = entry_date

SQLFiddleデモ:http ://www.sqlfiddle.com/#!12/50776/1

于 2013-02-10T23:32:47.723 に答える
1

単純にしないのはなぜですか。

SELECT citizen_name FROM citizens WHERE (country_ref, entry_date) IN (
    SELECT country_ref, MAX(entry_date) FROM citizens 
    LEFT JOIN countries ON country_id = country_ref 
    WHERE country_group = 1 GROUP BY country_ref
)

それは最善の計画ではないかもしれませんが、それは多くの要因に依存し、書くのは簡単です。

于 2013-02-10T23:10:15.823 に答える