Postgresql

如何加入 2 個表並用日期填充不匹配的條目

  • February 13, 2022

一家公司從其他公司購買零件。為了不使他們的伺服器超載,每 5 分鐘檢查一次零件的價格,以查看零件的價格是否發生了變化。因此,表格包含上次檢查公司零件的時間。

公司

零件

last_checked

如果我現在要查詢 last_checked,我可以為每家公司找出最久之前檢查過的元件(在這種情況下,Acme 公司的樹莓派和 Stark 行業的主機板型號 X4282。我會從某個地方讀取新數據並更新 date_last_checked到 now() 所以它現在有最新的日期。

但是,有時會引入一個新部分。所以表’Parts’會得到一個新行。這個新部分尚未在表 last_checked 中引入。

我想要的是一個顯示所有公司和所有部分的條目的查詢。表 last_checked 中已存在的公司/元件組合的日期將逐字使用,並且沒有公司的元件存在的條目應包含在 now() - 100 天的日期中。這樣,新零件將始終排在列表的首位。讀取後,新的公司/零件組合將插入 last_checked 並按照通常的周期開始。

我可以創建 2 個查詢,這些查詢結合起來具有正確的資訊;這將獲取表 last_checked 中尚不存在的 Acme 的所有部分

SELECT parts.id, now() - INTERVAL '100 DAYS' AS date 
FROM parts p 
WHERE p.id NOT IN (SELECT l.part_id_fk FROM last_checked l WHERE l.company_id_fk = 1)

這將為 Acme 選擇所有現有部分:

SELECT l.part_id_fk FROM last_checked l
WHERE l.company_id_fk = 1

這些組合的 2 個查詢是我需要的,但更通用,因此我可以從所有現有公司中選擇一家公司。然而,我不清楚如何將這些結合起來。我嘗試了一個 UNION 查詢,但由於日期不同,沒有匹配項,並且選擇了比需要更多的記錄。我也不知道如何在兩個查詢中檢查公司 ID。

我嘗試過 JOIN、LEFT JOIN、CROSS JOIN,但我所做的一切似乎都沒有得到正確的結果。我無法讓它工作的主要原因是因為我必須結合 2 個查詢,然後選擇 company_id,所以類似於:

SELECT * FROM
(Query1 combined with Query2) WHERE company_id = 1.

有針對這個的解決方法嗎?

SQL 確實允許/提供以下內容:

SELECT
 l.id,
 cp.company_id,
 cp.part_id,
 coalesce(l.date_last_checked, cast(now() - INTERVAL '100 DAYS' as timestamp(0))) AS date_last_checked
FROM last_checked l
right join (
 select c.id as company_id, p.id as part_id
 from Companies c
 cross join Parts p
 ) cp
 on l.company_id_fk = cp.company_id
 and l.part_id_fk = cp.part_id
WHERE cp.company_id = 1
;

但是,如果 Companies 和 Parts 增長,執行時間可能會成為一個問題。此時,您可能希望切換到UNION ALL兩個查詢中的一個,每個查詢都提供您需要的部分結果。

在行動中看到它:SQL Fiddle

如果需要調整/進一步詳細資訊,請發表評論。

引用自:https://dba.stackexchange.com/questions/307401