【问题标题】:SQL - query to report MAX DATE results or NULL resultsSQL - 查询以报告 MAX DATE 结果或 NULL 结果
【发布时间】:2013-10-14 22:17:32
【问题描述】:

我有一个包含 3 个表的 SQL 数据库:

  1. Customer record 表,保存主数据(每一行都是唯一的)
  2. Customer notes,每个笔记数据/时间戳(每个客户可能有很多笔记,或者根本没有)
  3. Product 表格,显示哪个客户购买了哪个产品

    表:tbl_Customer_Records
    CustomerID---- 公司名称----- 公司段----- 促销代码

    表格:tbl_Customer_Notes
    CustomerID---- 注意-----创建日期

    表:tbl_Customer_Products
    CustomerID---- 产品类别

我想要的是提取仅包含最新注释的客户记录列表,因此如果存在多个注释,则不会出现重复行。但如果没有备注根本不存在,我也希望我的报告包含客户记录。我已经使用 SELECT MAX 函数实现了第一部分,并且效果很好,问题是当我在下面的最后一行代码中添加 OR = NULL 子句时。这不起作用,我想不出解决办法。

任何建议将不胜感激!

SELECT        

[tbl_Customer_Records].[CustomerID], 
[tbl_Customer_Records].[Company Name], 
[tbl_Customer_Records].[Company Segment], 
[tbl_Customer_Records].[Promo Code], 
[tbl_Customer_Notes].[Note],
[tbl_Customer_Products].[Product Category]

FROM            

tbl_Customer_Records
LEFT OUTER JOIN tbl_Customer_Notes
ON tbl_Customer_Records.CustomerID = tbl_Customer_Notes.CustomerID 
LEFT OUTER JOIN tbl_Customer_Products
ON tbl_Customer_Records.CustomerID = tbl_Customer_Products.CustomerID

WHERE  
[Product Category] in ('Nuts','Bolts','Screws','Spanners') 

AND 

[Created Date] in (SELECT MAX ([Created Date]) FROM tbl.Customer_Notes GROUP BY [CustomerID]) 

OR tbl_Customer_Note.Note is null

【问题讨论】:

    标签: sql sql-server max


    【解决方案1】:

    有一些技巧可以进行这种查询(row_number 或加入分组数据),但我认为在您的情况下最简洁的方法是使用外部应用:

    select
       cr.[CustomerID], 
       cr.[Company Name], 
       cr.[Company Segment], 
       cr.[Promo Code], 
       cn.[Note],
       cp.[Product Category]
    from tbl_Customer_Records as cr
        left outer join tbl_Customer_Products as cp on cp.CustomerID = cr.CustomerID
        outer apply (
            select top 1
                t.[Note]
            from tbl_Customer_Notes as t
            where t.[CustomerID] = cr.[CustomerID]
            order by t.[Created_Date] desc
        ) as cn
    where
        cp.[Product Category] in ('Nuts','Bolts','Screws','Spanners') 
    

    将所有笨拙的table name.column name 更改为alias.column name,我认为这样更易读。

    或者:

    select
        cr.[CustomerID], 
        cr.[Company Name], 
        cr.[Company Segment], 
        cr.[Promo Code], 
        cn.[Note],
        cp.[Product Category]
    from tbl_Customer_Records as cr
        left outer join tbl_Customer_Products as cp on cp.CustomerID = cr.CustomerID
        left outer join tbl_Customer_Notes as cn on
            cn.CustomerID = cr.CustomerID and
            cn.[Created_Date] = (select max(t.[Created_Date]) from tbl_Customer_Notes as t where t.CustomerID = cr.CustomerID)
    where
        cp.[Product Category] in ('Nuts','Bolts','Screws','Spanners')
    

    【讨论】:

    • 感谢您的回答!关于笨拙的列名的观点,我以后会记住这一点。有趣的是,您的第一个解决方案返回 4,315 个结果,第二个返回 4,393 个结果 - 与 Deepshikha 的解决方案相同。感谢您的建议,我会记下语法以备将来使用。非常感谢您花时间提供帮助!丹尼尔
    • 如果有超过一条 max(Created_Date) 记录,则第一个返回任意记录
    • 啊,是的,我明白了。实际上,我确实有多个具有相同 CreatedDate 的注释,因此您的第一个解决方案在这种情况下效果更好。再次感谢。 (更改了接受的答案)。
    【解决方案2】:

    您可以在ON 谓词中添加过滤条件,以保留左表中的行,并从第一个 LEFT OUTER JOIN 运算符中仅从右表中获取所需的匹配行。以下查询应该有效:

    SELECT        
    CR.[CustomerID], 
    CR.[Company_Name], 
    CR.[Company_Segment], 
    CR.[Promo_Code], 
    CN.[Note],
    CP.[Product_Category]
    FROM            
    tbl_Customer_Records CR
    LEFT OUTER JOIN tbl_Customer_Notes CN
    ON CR.CustomerID = CN.CustomerID AND CN.[Created_Date] in (SELECT MAX ([Created_Date]) 
                                                               FROM tbl_Customer_Notes 
                                                               WHERE CR.CustomerID =  tbl_Customer_Notes.CustomerID 
                                                               GROUP BY [CustomerID]) 
    LEFT OUTER JOIN tbl_Customer_Products CP
    ON CR.CustomerID = CP.CustomerID
    WHERE  
    [Product_Category] in ('Nuts','Bolts','Screws','Spanners') 
    

    【讨论】:

    • 感谢您的代码 - 真的很感激。我运行了这段代码,它在我的数据集上返回了 4,393 个结果,所以我会将此代码保留为接受的答案。感谢您抽出宝贵时间提供帮助!干杯,丹尼尔
    【解决方案3】:

    应该可以,尝试使用 NULL 值:

    SELECT a.[CustomerID], 
           a.[Company Name], 
           a.[Company Segment], 
           a.[Promo Code], 
           a.[Note],
           a.[Product Category]
    FROM (
    SELECT        
    cr.[CustomerID], 
    cr.[Company Name], 
    cr.[Company Segment], 
    cr.[Promo Code], 
    cn.[Note],
    cp.[Product Category],
    ROW_NUMBER() OVER(PARTITION BY cr.[CustomerID] ORDER BY cn.[Created Date] DESC) as rnk
    FROM tbl_Customer_Records cr
    LEFT JOIN tbl_Customer_Notes cn
    ON cr.CustomerID = cn.CustomerID 
    LEFT JOIN tbl_Customer_Products cp
    ON cr.CustomerID = cp.CustomerID
    WHERE cp.[Product Category] in ('Nuts','Bolts','Screws','Spanners') )a
    WHERE a.rnk = 1
    

    【讨论】:

    • 感谢工厂提供的代码,非常感谢。有趣的是,该代码返回 4049 个结果,这比其他一些建议的解决方案要少一些。谢谢!
    【解决方案4】:

    尝试使用CustomerID not in (select CustomerID from tbl_Customer_Note)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-13
      • 1970-01-01
      • 1970-01-01
      • 2014-03-17
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      相关资源
      最近更新 更多