最大日期和第二个表中的where子句的条件左连接

时间:2018-08-17 16:33:49

标签: sql postgresql

我正在尝试将一个客户表与一个销售表结合在一起,在这里我显示数据库中所有客户的列表以及该客户可能在销售表中进行的任何有偿销售。现在,客户可以在销售表中具有多个销售行。 这是一个在销售表中有多个销售的客户的销售记录示例

enter image description here

在提取此记录时,我只想获取q(paid_mountamount)> 0的最大值(q_saledatetime)。 该客户上次向我们付款的时间显示 。因此,在这种情况下,我想为该客户支付的第二行的价格为8.90。 如果客户在销售表中没有记录,请以任何一种方式在列表中显示其姓名/详细信息。

我目前的失败是如何在“已付款金额+最高日期”列中添加where子句。

尝试A

select DISTINCT ON (q_customer.q_code)
q_customer.q_code, q_customer.q_name,  -- customer info  
MAX(q_saleheader.q_saledatetime) AS latestDate, q_saleheader.q_paidamount  -- saleheader info
FROM q_customer
LEFT JOIN q_saleheader ON (q_customer.q_code =  q_saleheader.q_customercode) 
group by q_customer.q_code, q_customer.q_name , q_saleheader.q_saledatetime, q_saleheader.q_paidamount
order by q_customer.q_code ASC

这将导致

enter image description here

因此,对于Fred Blogg来说,它是从第4行而不是第2行获取详细信息, (第一张图片) 。由于目前没有q_paidamount的规则

ATTEMPT B

SELECT 
customer.q_code, customer.q_name,  -- customer info
sale.q_saledatetime, sale.q_paidamount  -- sale info        
FROM q_customer customer
LEFT JOIN (SELECT * FROM q_saleheader WHERE q_saledatetime = 
(SELECT MAX(q_saledatetime) FROM q_saleheader b1 where q_paidamount > 0 )) 
sale ON sale.q_customercode = customer.q_code

这将导致

enter image description here

这似乎根本没有从销售表中获取任何信息。

更新:

仔细查看我的第一次尝试后,我修改了该语句,并提出了此解决方案,该解决方案可实现与Michal的回答相同的结果。我只是想知道以下方法是否存在任何陷阱或性能劣势。

select DISTINCT ON (q_customer.q_code)
q_customer.q_code, q_customer.q_name,  -- customer info  
q_saleheader.q_saledatetime, q_saleheader.q_paidamount  -- saleheader   info
FROM q_customer
LEFT JOIN q_saleheader ON (q_customer.q_code =   q_saleheader.q_customercode AND 
q_saleheader.q_paidamount > 0 ) 
group by q_customer.q_code, q_customer.q_name ,  q_saleheader.q_saledatetime, 
q_saleheader.q_paidamount
order by q_customer.q_code ASC, q_saleheader.q_saledatetime DESC 

主要更改是在联接上添加AND q_saleheader.q_paidamount> 0和q_saleheader.q_saledatetime DESC,以确保获取该相关数据的第一行。如前所述,Michal的答案和此解决方案均能达到相同的结果。只是对两种方式的陷阱感到好奇。

1 个答案:

答案 0 :(得分:2)

尝试此查询:

SELECT c.q_code,
       c.q_name,
       CASE WHEN q_saledatetime <> '1900-01-01 00:00:00.000' THEN q_saledatetime END q_saledatetime,
       q_paidamount
FROM (
    SELECT c.q_code, 
           c.q_name,
           coalesce(s.q_saledatetime, '1900-01-01 00:00:00.000') q_saledatetime, --it will indicate customer with no data
           s.q_paidamount,
           ROW_NUMBER() OVER (PARTITION BY c.q_code ORDER BY COALESCE(s.q_saledatetime, '1900-01-01') DESC) rn
    FROM q_customer c
    LEFT JOIN (SELECT q_saledatetime,
                      q_paidamount
               FROM q_saleheader
               WHERE q_paidamount > 0) s 
    ON c.q_code = s.q_customercode
) c WHERE rn = 1