我编写了以下代码,其中在 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和查询应该如何完成?
由于 CTE 旨在过滤掉特定的客户 ID,因此带有
LEFT JOIN
检查的 NULL
将干净地完成此操作。定义 CTE(测试)以识别要排除的客户。在主查询和基于 customerid 的测试 CTE 之间使用 LEFT JOIN
,最后在 WHERE
子句中,检查测试 CTE 中的 NULL
值以排除匹配的客户 ID。
下面是一个示例,其中我添加了一些新客户并订购了不同类别的产品(例如 ProductCategoryID = 8)
在该客户列表中,一位名为 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;