1
Product Name    Product Id  Product Status
A               1           Rollout
A               1           Storage
A               1           Delivered
A               5           Storage
B               2           Rollout
C               3           Rollout
A               4           Rollout
A               5           Rollout
B               6           Rollout
C               7           Rollout

在上表中,我想写下面的查询,它应该返回类似的结果

Product Name QOH
A            1
B            0
C            0

询问:

SELECT Product Name, Count(Product Id) 
FROM table_t1 
WHERE Product Status IN ('Storage') AND Product Status NOT IN ('Delivered')

但是上面的查询返回以下结果

Product Name QOH
A            2
B            0
C            0

请帮忙。

4

5 回答 5

2

您应该能够使用以下查询:

select distinct t.[product name], 
  coalesce(p.QOH, 0) QOH
from yourtable t
left join
(
  select t1.[product name], count(*) QOH
  from yourtable t1
  where [Product Status] = 'Storage'
    and not exists (select [product id]
                    from yourtable t2
                    where [Product Status] = 'Delivered'
                      and t1.[product id] = t2.[product id])
  group by t1.[product name]
) p
  on t.[product name] = p.[product name]

请参阅带有演示的 SQL Fiddle

您原始查询的问题是产品不能同时具有两种状态。您试图返回状态为Storageand的行,这在Delivered逻辑上是不可能的。

我使用了一个子查询,它返回状态为 的行Storage,但是在product id表中也没有状态为的行Delivered(这是子句not exists中的)。where

获得这些结果后,您必须重新加入表以返回所有不同的产品。

此查询给出结果:

| PRODUCT NAME | QOH |
----------------------
|            A |   1 |
|            B |   0 |
|            C |   0 |
于 2013-03-27T11:36:40.307 回答
1

我不完全同意这不合逻辑的说法。同一列上的 IN 和 NOT IN 子句是合法且合乎逻辑的。这就像在做Set Minus (Set A - Set B)

话虽如此,上面的例子

SELECT Product Name, Count(Product Id) 
FROM table_t1 
WHERE Product Status IN ('Storage') AND Product Status NOT IN ('Delivered')

SELECT Product Name, Count(Product Id) 
FROM table_t1 
WHERE Product Status IN ('Storage')

因此结果。在这个例子中不是很有用。但有时将 IN 和 NOT IN 一起使用是有用的,即使在同一列中也是如此。

例如,我有一个很长的要包含在 IN 中的项目的白名单,同时,我想过滤掉现有黑名单中的一些项目。当然,我们可以先做 Set Minus,然后让查询做IN (Result of whitelist - blacklist)。但我们也可以这样做IN (whitelist) AND NOT IN (blacklist)

于 2021-05-01T14:14:01.440 回答
0
SELECT ProductName, count(distinct ProductID)
from(
SELECT ProductName, ProductID
FROM Table_1
GROUP BY ProductName, ProductID
HAVING MAX(ProductStatus)='Storage' 
and MIN(ProductStatus)<>'Delivered')
X
GROUP BY ProductName
于 2013-03-29T10:03:51.053 回答
0

我可以建议类似的变体,没有不必要的连接和函数调用 -

DECLARE @temp TABLE
(
      ProductName CHAR(1)    
    , ProductID INT  
    , ProductStatus VARCHAR(10)
)

INSERT INTO @temp (ProductName, ProductID, ProductStatus)
VALUES 
    ('A', 1, 'Rollout'),
    ('A', 1, 'Storage'),
    ('A', 1, 'Delivered'),
    ('A', 5, 'Storage'),
    ('B', 2, 'Rollout'),
    ('C', 3, 'Rollout'),
    ('A', 4, 'Rollout'),
    ('A', 5, 'Rollout'),
    ('B', 6, 'Rollout'),
    ('C', 7, 'Rollout')

SELECT 
      t.ProductName 
    , [Count] = COUNT(1)
FROM @temp t
WHERE t.ProductStatus = 'Storage'
    AND NOT EXISTS ( 
        SELECT 1
        FROM @temp t2
        WHERE t2.ProductStatus = 'Delivered'
            AND t.ProductID = t2.ProductID 
    )
GROUP BY ALL t.ProductName
于 2013-04-04T12:17:40.220 回答
0

您在开始时通过 [产品状态] 过滤表格,因此您不会以这种方式看到 B 和 C。您需要使用分组:

Select 
    [Product Name]
    ,QOH = sum(case when [Product Status]='Storage' then 1 else 0 end)
group by 
    [Product Name]
于 2013-03-27T11:19:00.367 回答