2

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

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

    表:tbl_Customer_Records
    CustomerID---- Company Name-----Company Segment----- Promo Code

    表:tbl_Customer_Notes
    CustomerID---- Note-----Created Date

    表: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
4

4 回答 4

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') 
于 2013-10-14T10:12:42.127 回答
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
于 2013-10-14T11:36:56.860 回答
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 namealias.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')
于 2013-10-14T11:42:46.603 回答
0

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

于 2013-10-14T09:40:00.400 回答