SQL - 查询MAX DATE结果或NULL结果的查询

时间:2013-10-14 09:31:45

标签: sql sql-server max

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

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

    表:tbl_Customer_Records
    客户ID ----公司名称-----公司分部-----促销代码

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

    表:tbl_Customer_Products
    客户ID ----产品类别

  4. 我想要的是提取仅包含最新笔记的客户记录列表,因此如果存在多个笔记,则没有重复的行。但是,如果没有备注存在,我还希望我的报告包含客户记录。我已经使用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
    

4 个答案:

答案 0 :(得分:1)

您可以在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') 

答案 1 :(得分:1)

应该有效,尝试使用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

答案 2 :(得分: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')

答案 3 :(得分:0)

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