如何使用具有特定条件的 case 语句总结唯一值

Posted

技术标签:

【中文标题】如何使用具有特定条件的 case 语句总结唯一值【英文标题】:How to sum up unique values using case statements having certain conditions 【发布时间】:2019-06-30 00:22:44 【问题描述】:

我有一张桌子,可能有相同的物品但尺寸不同,我想计算不止一种尺寸的物品(例如,S 码的奇迹衬衫,M 码将计为“1”),但仍然是能够数出多少个 S 和 M。我有 2 个我想得到的结果。详情请见下文。

TABLE B   

ITEM_NO ITEM             
=========================
3130C   MARVEL_SHIRT     
1845C   SPONGEBOB_BOXERS 
A900C   CK_COAT          
A988C   RIDER_JEANS      


TABLE C

ITEM_NO SIZE          
===============
3130C   S             
3130C   M             
1845C   M             
A900C   L             
A988C   M     -

我试着只计算它,但它不正确,因为它计算了有多少不同的尺寸

select (case substr(item_no, 5, 1)
            when 'C' then 'clothes'
            when 'T' then 'toys'
            else 'misc' 
        end) inv, 
       count(item_no) total 
       ,sum (case when C.size = 'S' then 1 else 0 end) AS small
       ,sum (case when C.size = 'M' then 1 else 0 end) AS med
       ,sum (case when C.size = 'L' then 1 else 0 end) AS large   
       ,count (distinct C.size) AS multiple_sizes
        from B left outer join C on B.item_no = C.item_no 
        group by substr(item_no, 5, 1);

实际结果(不正确):

INV     TOTAL   Small   Med   Large   Multiple_Sizes
==========================================================
CLOTHES    4       1    3       1       3

期望/预期结果:

INV     TOTAL   Small   Med   Large   Multiple_Sizes
==========================================================
CLOTHES    4       1    3       1       1

在这种情况下,下面是另一个可能的期​​望结果:如果不应该单独计算具有多个尺寸的那些(即 Marvel 衬衫有多个尺寸,因此它不会计算 S 或 M,因为它已经被计算在 Multiple_Sizes 下) ?

INV     TOTAL   Small   Med   Large     Multiple_Sizes
==========================================================
CLOTHES    4       0    2     1        1

【问题讨论】:

为什么 Multiple_Size = 3 不正确? S、M 和 L 不是多种尺寸的一部分吗? 您的实际结果与查询不符。它肯定会为您的数据返回四行,因为您有四种不同的衣服。 对不起,伙计们,这是一个糟糕的例子,我会做一个更好的例子,但不知道我应该把它贴在这里还是发一个新的帖子...... 【参考方案1】:

您可能需要按项目编号 (2) 按项目类别分组两次 (1):

SELECT SUBSTR(item_no, 5, 1) AS category
     , COUNT(*) AS count_products
     , SUM(count_small) AS small
     , SUM(count_med) AS med
     , SUM(count_large) AS large
     , SUM(CASE WHEN count_small + count_med + count_large > 1 THEN 1 END) AS has_multiple
FROM (
    SELECT b.ITEM_NO
         , COUNT(CASE WHEN c.SIZE = 'S' THEN 1 END) AS count_small
         , COUNT(CASE WHEN c.SIZE = 'M' THEN 1 END) AS count_med
         , COUNT(CASE WHEN c.SIZE = 'L' THEN 1 END) AS count_large
    FROM b
    LEFT JOIN c ON b.item_no = c.item_no
    GROUP BY b.ITEM_NO
) x
GROUP BY SUBSTR(item_no, 5, 1)
| category | count_products | small | med | large | has_multiple |
| C        | 4              | 1     | 3   | 1     | 1            |

还有变化:

SELECT SUBSTR(item_no, 5, 1) AS category
     , COUNT(*) AS count_products
     , SUM(CASE WHEN count_small + count_med + count_large = 1 THEN count_small END) AS small
     , SUM(CASE WHEN count_small + count_med + count_large = 1 THEN count_med   END) AS med
     , SUM(CASE WHEN count_small + count_med + count_large = 1 THEN count_large END) AS large
     , SUM(CASE WHEN count_small + count_med + count_large > 1 THEN 1 END) AS has_multiple
FROM (
    SELECT b.ITEM_NO
         , COUNT(CASE WHEN c.SIZE = 'S' THEN 1 END) AS count_small
         , COUNT(CASE WHEN c.SIZE = 'M' THEN 1 END) AS count_med
         , COUNT(CASE WHEN c.SIZE = 'L' THEN 1 END) AS count_large
    FROM b
    LEFT JOIN c ON b.item_no = c.item_no
    GROUP BY b.ITEM_NO
) x
GROUP BY SUBSTR(item_no, 5, 1)
| category | count_products | small | med | large | has_multiple |
| C        | 4              | 0     | 2   | 1     | 1            |

【讨论】:

谢谢,我能够按照你的逻辑 - 但我仍然无法让“has_multiple”工作,它将所有内容显示为“1”......我会发布一个更现实的例子.不确定我是否可以编辑这篇文章 - 或者将其标记为已解决然后发布一个新的...... 这符合您的测试用例。如果逻辑不同,请考虑提出一个新问题。【参考方案2】:
--creando tabla
create table #temp (itemId int, size nvarchar(1))

--insertando valores
insert into #temp values (1,'S')
insert into #temp values (1,'M')
insert into #temp values (2,'M')
insert into #temp values (3,'L')
insert into #temp values (4,'M')


-- table of Different Item Codes

    select 
        itemId
    into #masDeUnItem
    from
    (select itemId,size from #temp group by itemId,size) t1
    group by itemId 
    having count(1) > 1


-- Variable of Counting different Items
declare @itemsDistintos int 


-- Providing Value to Variable
select @itemsDistintos = count(1) from 
(
    select * from #masDeUnItem
) t1


--Outcome 1
select count(distinct(itemId)) TOTAL
,
sum(case when size = 'S' then 1 else 0 end) SMALL
, sum(case when size = 'M' then 1 else 0 end) MEDIUM
, sum(case when size = 'L' then 1 else 0 end) LARGE
,  @itemsDistintos as Multiple_Sizes
from #temp


--Outcome 2
select count(distinct(a.itemId)) TOTAL
,
sum(case when size = 'S' and b.itemId is null then 1 else 0 end) SMALL
, sum(case when size = 'M' and b.itemId is null then 1 else 0 end) MEDIUM
, sum(case when size = 'L' and b.itemId is null then 1 else 0 end) LARGE
,  @itemsDistintos as Multiple_Sizes
from #temp a 
left join #masDeUnItem b 
on a.itemId = b.itemId 

【讨论】:

以上是关于如何使用具有特定条件的 case 语句总结唯一值的主要内容,如果未能解决你的问题,请参考以下文章

带有 CASE 条件和 SUM() 的 SELECT 查询

SQL - 使用具有多个 IS NULL、IS NOT NULL 的 CASE 语句

oracle语句中when条件接不存在怎么写

程序流程控制2

如何使用 SQL 中的 Case 语句将数据插入临时表

Golang switch语句总结