8

我的情況:Postgres的:左邊有順序加入和限制1

Table1 has a list of companies. 
Table2 has a list of addresses. 
Table3 is a N relationship of Table1 and Table2, with fields 'begin' and 'end'. 

因爲公司可能會隨着時間的推移移動,一個LEFT JOIN其中多個記錄中每家公司的結果。

begin and end fields are never NULL。找到最新地址的解決方案是使用ORDER BY being DESC,並刪除舊地址是LIMIT 1

如果查詢只能帶1個公司,那麼這很好。但是我需要一個帶有所有Table1記錄的查詢,並加入他們當前的Table2地址。因此,必須在LEFT JOIN的ON子句中刪除過期的數據(AFAIK)。

任何想法如何建立條款不創建重複的Table1公司,並帶來最新的地址?

回答

3

我設法使用Windows功能來解決這個問題:

WITH ranked_relationship AS(
    SELECT 
     * 
     ,row_number() OVER (PARTITION BY fk_company ORDER BY dt_start DESC) as dt_last_addr 
    FROM relationship 
) 

SELECT 
    company.* 
    address.*, 
    dt_last_addr as dt_relationship 
FROM 
    company 
    LEFT JOIN ranked_relationship as relationship 
      ON relationship.fk_company = company.pk_company AND dt_last_addr = 1 
    LEFT JOIN address ON address.pk_address = relationship.fk_address 

ROW_NUMBER()創建一個int計數器爲每個記錄,裏面每個窗口基於fk_company。對於每個窗口,具有最新日期的記錄首先以等級1,然後dt_last_addr = 1確保每個fk_company僅發生一次JOIN,並且記錄具有最新地址。

窗口函數功能非常強大,很少有人使用它們,它們避免了許多複雜的連接和子查詢!

9

在連接條件中使用帶有max()函數的從屬子查詢。
東西就像這個例子:

SELECT * 
FROM companies c 
LEFT JOIN relationship r 
ON c.company_id = r.company_id 
    AND r."begin" = (
     SELECT max("begin") 
     FROM relationship r1 
     WHERE c.company_id = r1.company_id 
    ) 
INNER JOIN addresses a 
ON a.address_id = r.address_id 

演示:http://sqlfiddle.com/#!15/f80c6/2

+0

不錯,在sqlfiddle - 我只看到jsfiddle到現在,但sqlfiddle似乎超級有益! – dwanderson