如果一个是多个,则通过同一列中的两个值过滤结果

时间:2021-02-22 00:32:20

标签: sql sql-server tsql

我正在尝试列出从 ProductCategoryKey 1 购买的客户,如果这些客户购买了 ProductCategoryKEY 3 不止一次,则只显示该客户的一行。到目前为止,我的代码只过滤了 PC Key 1。我怎么能说“在购买了 PC Key 1 的人中,有多少人至少购买了两次 PC Key 3 并且只向那个人展示了一次?”

SELECT DISTINCT C.FirstName, C.LastName, PC.EnglishProductCategoryName
FROM dbo.FactInternetSales AS I
INNER JOIN dbo.DimCustomer AS C
    ON I.CustomerKey = C.CustomerKey
INNER JOIN dbo.DimProduct AS P
    ON I.ProductKey = P.ProductKey
INNER JOIN dbo.DimProductSubcategory AS SC
    ON P.ProductSubcategoryKey = SC.ProductSubcategoryKey
INNER JOIN dbo.DimProductCategory as PC
    ON SC.ProductCategoryKey = PC.ProductCategoryKey
WHERE PC.ProductCategoryKey = 1
ORDER BY C.LastName ASC, FirstName ASC;

使用 Microsoft SQL Server 2019 ADventureWorksDW2017

2 个答案:

答案 0 :(得分:1)

我非常喜欢使用临时表或变量表来进一步过滤数据。第一个查询获取 PC Key 为 1 和 3 的所有客户,并将这些记录插入到临时表中。然后,第二个查询使用聚合和 GROUP BY 子句对 PC Key 为 3 的所有行进行计数,然后是 HAVING 子句,其中计数 > 2。GROUP BY 子句在第二个查询有效地为您的最后一个要求创建了一个不同的记录集。

为了便于阅读,我将查询分解为两个查询。您也可以使用嵌套子查询来实现相同的结果。

SELECT DISTINCT C.FirstName, C.LastName, PC.EnglishProductCategoryName, 
    PC.ProductCategoryKey
into #temp1
FROM  dbo.FactInternetSales AS I
INNER JOIN dbo.DimCustomer AS C
    ON I.CustomerKey = C.CustomerKey
INNER JOIN dbo.DimProduct AS P
    ON I.ProductKey = P.ProductKey
INNER JOIN dbo.DimProductSubcategory AS SC
    ON P.ProductSubcategoryKey = SC.ProductSubcategoryKey
INNER JOIN dbo.DimProductCategory as PC
    ON SC.ProductCategoryKey = PC.ProductCategoryKey
WHERE PC.ProductCategoryKey = 1
    AND PC.ProductCategoryKey = 3
ORDER BY C.LastName ASC, FirstName ASC

SELECT  FirstName, LastName, EnglishProductCategoryName, COUNT(*)
FROM    #temp1
WHERE   ProductCategoryKey = 3
GROUP BY FirstName, LastName, EnglishProductCategoryName
HAVING COUNT(*) > 2

答案 1 :(得分:0)

除非您遇到性能问题,否则我会在临时表上使用 CTE。通过这种方式,您可以获得单个执行计划,这通常比拆分为两个执行计划(如使用临时表那样)更好(除非它不是)。

此外,除非您的逻辑有误,否则您不需要 distinct。正确分组的查询很少需要 distinct

WITH cte AS (
    SELECT C.FirstName, C.LastName, PC.EnglishProductCategoryName, PC.ProductCategoryKey
    FROM  dbo.FactInternetSales AS I
    INNER JOIN dbo.DimCustomer AS C ON I.CustomerKey = C.CustomerKey
    INNER JOIN dbo.DimProduct AS P ON I.ProductKey = P.ProductKey
    INNER JOIN dbo.DimProductSubcategory AS SC ON P.ProductSubcategoryKey = SC.ProductSubcategoryKey
    INNER JOIN dbo.DimProductCategory AS PC ON SC.ProductCategoryKey = PC.ProductCategoryKey
    WHERE PC.ProductCategoryKey = 1 AND PC.ProductCategoryKey = 3
)
SELECT FirstName, LastName, EnglishProductCategoryName, COUNT(*)
FROM cte
WHERE ProductCategoryKey = 3
GROUP BY FirstName, LastName, EnglishProductCategoryName
HAVING COUNT(*) > 2
ORDER BY LastName ASC, FirstName ASC;

我假设逻辑是正确的,因为没有样本数据和预期结果很难知道。

相关问题