【发布时间】:2020-11-23 09:03:53
【问题描述】:
我正在尝试在 SQL 中执行左连接,我需要 检查多个匹配条件,并且仅在某个 之后在右表中保留 第一个匹配 >对右表进行排序操作。
下面是我的左桌。 (无 Null 值)
| Date | Customer | Shop | Product | Customer_Score |
|---|---|---|---|---|
| 1/1/2020 | C1 | S1 | P1 | 2 |
| 1/2/2020 | C2 | S1 | P2 | 8 |
| 1/5/2020 | C3 | S2 | P1 | 6 |
| 1/6/2020 | C4 | S2 | P2 | 10 |
| 1/7/2020 | C1 | S2 | P3 | 2 |
| 1/8/2020 | C2 | S2 | P4 | 4 |
这是正确的表 (Null 值只能在 Product 列中使用)
| Shop | Product | Min_Customer_Score | Valid_From | Valid_To | Percent_Discount |
|---|---|---|---|---|---|
| S1 | P1 | 4 | 1/1/2020 | 1/5/2020 | 10 |
| S1 | P1 | 5 | 1/1/2020 | 1/5/2020 | 11 |
| S1 | P1 | 7 | 1/1/2020 | 1/5/2020 | 12 |
| S1 | 5 | 1/1/2020 | 1/5/2020 | 13 | |
| S2 | P1 | 4 | 1/1/2020 | 1/5/2020 | 14 |
| S2 | P2 | 4 | 1/1/2020 | 1/5/2020 | 15 |
| S2 | 6 | 1/1/2020 | 1/5/2020 | 16 | |
| S2 | 9 | 1/1/2020 | 1/5/2020 | 17 | |
| S2 | P1 | 4 | 1/6/2020 | 1/8/2020 | 18 |
| S2 | P2 | 4 | 1/6/2020 | 1/8/2020 | 19 |
| S2 | 6 | 1/6/2020 | 1/8/2020 | 20 | |
| S2 | 9 | 1/6/2020 | 1/8/2020 | 21 |
我想首先按 Product(最后为 null)然后按 Min_Customer_Score(升序)对正确的表进行排序。 然后我想从匹配以下条件的第一行中提取 Min_Customer_Score 和 Discount 值:
- Left.Date >= Right.Valid_From
- Left.Date
- Left.Shop = Right.Shop
- Left.Product = Right.Product 或 Right.Product = null
- Left.Customer_Score >= Right.Min_Customer_Score
我的最终结果应该如下所示。
| Date | Customer | Shop | Product | Customer_Score | Min_Customer_Score | Percent_Discount |
|---|---|---|---|---|---|---|
| 1/1/2020 | C1 | S1 | P1 | 2 | null | null |
| 1/2/2020 | C2 | S1 | P2 | 8 | 5 | 13 |
| 1/5/2020 | C3 | S2 | P1 | 6 | 4 | 14 |
| 1/6/2020 | C4 | S2 | P2 | 10 | 4 | 19 |
| 1/7/2020 | C1 | S2 | P3 | 2 | null | null |
| 1/8/2020 | C2 | S2 | P4 | 4 | null | null |
基本上,我想为每次购买找到合适的折扣,考虑 Right.Product 中的空值作为默认折扣,适用于所有其他产品。
我熟悉左连接以及在 SQL 中使用子查询。但我什至不明白从哪里开始做如此复杂的查询。我还提到了其他建议使用ROW_NUMBER() OVER (PARTITION BY 的答案,但无法解决这种情况。
编辑: 到目前为止,这是我能够解决的问题。
SELECT left_table.*, right_table.Percent_Discount, right_table.Min_Customer_Score
, ROW_NUMBER() OVER (
PARTITION BY left_table.Date, left_table.Customer, left_table.Shop, left_table.Product
ORDER BY right_table.Product DESC right_table.Min_Customer_Score ASC) as row_num
LEFT JOIN right_table
ON left_table.Date >= right_table.Valid_From
AND left_table.Date <= right_table.Valid_To
AND left_table.Shop>= right_table.Shop
AND (left_table.Product = right_table.Product OR right_table.Product is NULL)
AND left_table.Customer_Score >= right_table.Min_Customer_Score
WHERE row_num = 1
但它给了我以下错误
ERROR: column "row_num" does not exist
LINE: WHERE row_num = 1
【问题讨论】:
-
使用
row_number是正确的方法。按照您在问题中概述的方式执行left join,在select中包含row_number,然后过滤row_number = 1中的那些。您的partition by是您只想从中返回一行的值组,order by确定该partition中的行顺序。尝试编写此脚本并将您尝试过的内容添加到此问题中,如果您无法使其正常工作。 -
感谢@iamdave,我按照您的建议尝试了并在问题中添加了该代码
标签: sql postgresql join