简体   繁体   中英

SQL case when to count null values

I'm writing a query, data looks like this:

Data:

ID name date_completed version
1 Sydney 2021-01-01 A
2 Melbourne 2021-01-5 A
3 Sydney 2021-01-10 B
4 Sydney 2021-02-01 A
5 Melbourne 2021-02-07 A
6 Melbourne 2021-02-13 A

My query:

SELECT name
         , '01-01-21' AS Date
         , (case
                when version = 'A' then 'A'
                when version = 'B' then 'B'
        end)          AS 'Type'
         , (case
                when version = 'A' then count(ID)
                when version = 'B' then count(ID)
        end)          AS 'Count'
    FROM table
    WHERE date_completed between '2021-01-01' and '2021-01-31'
    GROUP BY name, version

    UNION

SELECT name
         , '01-02-21' AS Date
         , (case
                when version = 'A' then 'A'
                when version = 'B' then 'B'
        end)          AS 'Type'
         , (case
                when version = 'A' then count(ID)
                when version = 'B' then count(ID)
        end)          AS 'Count'
    FROM table
    WHERE date_completed between '2021-02-01' and '2021-02-28'
    GROUP BY name, version

Output:

name date Type count
Sydney 01-01-21 A 1
Melbourne 01-01-21 A 1
Sydney 01-01-21 B 1
Sydney 01-02-21 A 1
Melbourne 01-02-21 A 2

The issue I'm facing is that because version A/B doesn't exist for some months it will not show a row with count = 0

I'm trying to create an output like this:

name date Type count
Sydney 01-01-21 A 1
Melbourne 01-01-21 A 1
Sydney 01-01-21 B 1
Melbourne 01-01-21 B 0
Sydney 01-02-21 A 1
Melbourne 01-02-21 A 2
Sydney 01-02-21 B 0
Melbourne 01-02-21 B 0

Is this something that can be done without having to create a separate table with name, date & type and using LEFT JOIN between the two tables?

Also is there a better way of dealing with querying data within a specific month without having to union multiple select statements?

Thanks

You need to find all combination of name - month - version and then left join to your table and then perform the count()

If you have individual table of name, version, you may use that instead of finding the distinct value from the table ( select distinct name from tbl )

with 
name_mth_ver as
(
    select name, mth_st, mth_en, version
    from
    (
        select distinct name
        from   tbl
    ) n
    cross join
    (
         select distinct
                mth_st = convert(date, dateadd(month, datediff(month, 0, date_completed), 0)),
                mth_en = convert(date, dateadd(month, datediff(month, 0, date_completed) + 1, -1))
         from   tbl
    ) m
    cross join
    (
        select distinct version
        from   tbl
    ) v
)
select n.name
       , n.mth_st AS [Date]
       , n.version AS [Type]
       , count(t.ID) AS [Count]
from   name_mth_ver n
       left join tbl t on  n.name    = t.name
                       and n.mth_st <= t.date_completed
                       and n.mth_en >= t.date_completed
                       and n.version = t.version
group by n.name, n.mth_st, n.version

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM