完成在 WHERE 子句中用作过滤器的 CTE

问题描述 投票:0回答:1

我编写了以下代码,其中在 WHERE 子句中包含子查询,并且它工作得很好。然后我开始研究 CTE,以满足根据识别的客户 ID 过滤数据的相同目的。据我了解,建议使用 CTE 用于此目的,因为它们可以保持代码整洁且有组织。然而,我在完成 CTE 方面遇到了困难,因为我不知道应该在其中包含哪些列才能加入最后一步。

select 
    cus.FirstName as First_Name,
    cus.LastName as Last_Name,
    cus.customerid as Customer_ID,
    prod.name as Product_Name, 
    prod.ProductID as Product_ID,
    prod.ProductCategoryID as Product_Category_ID
from saleslt.SalesOrderHeader hd  
left join saleslt.SalesOrderDetail sod ON hd.SalesOrderID = sod.SalesOrderID
left join saleslt.customer cus ON cus.CustomerID = hd.CustomerID
left join saleslt.product prod ON prod.ProductID = sod.ProductID
where cus.customerid NOT IN (select 
                                min(cus.customerid) as Customer_ID
                            from saleslt.SalesOrderHeader hd  
                            left join saleslt.SalesOrderDetail sod ON hd.SalesOrderID = sod.SalesOrderID
                            left join saleslt.customer cus ON cus.CustomerID = hd.CustomerID
                            left join saleslt.product prod ON prod.ProductID = sod.ProductID
                            where prod.productcategoryid in ('5','6','7')
                            group by cus.customerid
                            )
ORDER BY cus.FirstName, cus.LastName
;WITH test as (
select min(cus.customerid) as Customer_ID
from saleslt.SalesOrderHeader hd  
left join saleslt.SalesOrderDetail sod ON hd.SalesOrderID = 
sod.SalesOrderID
left join saleslt.customer cus ON cus.CustomerID = hd.CustomerID
left join saleslt.product prod ON prod.ProductID = sod.ProductID
where prod.productcategoryid in ('5','6','7')
group by cus.customerid
)
select 
    cus.FirstName as First_Name,
    cus.LastName as Last_Name,
    cus.customerid as Customer_ID,
    prod.name as Product_Name, 
    prod.ProductID as Product_ID,
    prod.ProductCategoryID as Product_Category_ID
from saleslt.SalesOrderHeader hd  
left join saleslt.SalesOrderDetail sod ON hd.SalesOrderID = sod.SalesOrderID
left join saleslt.customer cus ON cus.CustomerID = hd.CustomerID
left join saleslt.product prod ON prod.ProductID = sod.ProductID
left join test t ON t.??? = ???
where cus.customerid NOT IN test.customerID

查询的重点是在最终查询中排除客户(如果客户包含在 CTE 中)。整体的join和查询应该如何完成?

azure t-sql
1个回答
0
投票

由于 CTE 旨在过滤掉特定的客户 ID,因此带有

LEFT JOIN
检查的
NULL
将干净地完成此操作。定义 CTE(测试)以识别要排除的客户。在主查询和基于 customerid 的测试 CTE 之间使用
LEFT JOIN
,最后在
WHERE
子句中,检查测试 CTE 中的
NULL
值以排除匹配的客户 ID。

下面是一个示例,其中我添加了一些新客户并订购了不同类别的产品(例如 ProductCategoryID = 8)

enter image description here

在该客户列表中,一位名为 Alice Brown 的客户是唯一未购买类别 5、6 或 7 中产品的客户

正如您在下面的输出中看到的,

ExcludedCustomers
CTE 成功过滤掉了在这些指定类别中进行购买的客户。

;WITH ExcludedCustomers AS (
    SELECT MIN(cus.CustomerID) AS Customer_ID
    FROM saleslt.SalesOrderHeader AS hd
    LEFT JOIN saleslt.SalesOrderDetail AS sod ON hd.SalesOrderID = sod.SalesOrderID
    LEFT JOIN saleslt.Customer AS cus ON cus.CustomerID = hd.CustomerID
    LEFT JOIN saleslt.Product AS prod ON prod.ProductID = sod.ProductID
    WHERE prod.ProductCategoryID IN (5, 6, 7)
    GROUP BY cus.CustomerID
)
SELECT 
    cus.FirstName AS First_Name,
    cus.LastName AS Last_Name,
    cus.CustomerID AS Customer_ID,
    prod.Name AS Product_Name, 
    prod.ProductID AS Product_ID,
    prod.ProductCategoryID AS Product_Category_ID
FROM saleslt.SalesOrderHeader AS hd
LEFT JOIN saleslt.SalesOrderDetail AS sod ON hd.SalesOrderID = sod.SalesOrderID
LEFT JOIN saleslt.Customer AS cus ON cus.CustomerID = hd.CustomerID
LEFT JOIN saleslt.Product AS prod ON prod.ProductID = sod.ProductID
LEFT JOIN ExcludedCustomers AS ec ON cus.CustomerID = ec.Customer_ID
WHERE ec.Customer_ID IS NULL
ORDER BY cus.FirstName, cus.LastName;

enter image description here

参考 - https://learn.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql?view=sql-server-ver16

© www.soinside.com 2019 - 2024. All rights reserved.