Include all possible values of sub-categories under each category












3















How can it be achieved in MS SQL 2016, when I need to always see every state under all existing categories even if there are no records, which satisfy the state formula?



Under a and b below I always want to see all three of later, earlier, and same with null counts whenever there is no corresponding record.



I guess it should be achievable with some sort of cross join?..



declare @t table (tid int not null identity(1,1) primary key clustered
,tcat char(1)
,tdat1 date
,tdat2 date
)

insert into @t select * from (values
('a', '2019-01-01', '2019-02-01')
,('a', '2019-02-01', '2019-01-01')
,('b', '2019-02-01', '2019-01-01')
,('b', '2019-01-01', '2019-01-01')
)as t(tcat, tdat1, tdat2)

select
tcat as category
,case
when tdat1 > tdat2 then 'later'
when tdat1 < tdat2 then 'earlier'
when tdat1 = tdat2 then 'same'
end as state
,count(1) as howmany
from @t
group by
tcat
,case
when tdat1 > tdat2 then 'later'
when tdat1 < tdat2 then 'earlier'
when tdat1 = tdat2 then 'same'
end









share|improve this question









New contributor




user172009 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • 1





    It's not absolutely clear what your intended result is. Are you looking for your final result to have later, earlier, and same columns? Or do you want three rows for each category, correspond to those three values. I recommend you edit in an example of the expected output, as that may make your question clearer.

    – RDFozz
    2 hours ago











  • are A and B fixed categories or can you change them?

    – seventyeightist
    2 hours ago
















3















How can it be achieved in MS SQL 2016, when I need to always see every state under all existing categories even if there are no records, which satisfy the state formula?



Under a and b below I always want to see all three of later, earlier, and same with null counts whenever there is no corresponding record.



I guess it should be achievable with some sort of cross join?..



declare @t table (tid int not null identity(1,1) primary key clustered
,tcat char(1)
,tdat1 date
,tdat2 date
)

insert into @t select * from (values
('a', '2019-01-01', '2019-02-01')
,('a', '2019-02-01', '2019-01-01')
,('b', '2019-02-01', '2019-01-01')
,('b', '2019-01-01', '2019-01-01')
)as t(tcat, tdat1, tdat2)

select
tcat as category
,case
when tdat1 > tdat2 then 'later'
when tdat1 < tdat2 then 'earlier'
when tdat1 = tdat2 then 'same'
end as state
,count(1) as howmany
from @t
group by
tcat
,case
when tdat1 > tdat2 then 'later'
when tdat1 < tdat2 then 'earlier'
when tdat1 = tdat2 then 'same'
end









share|improve this question









New contributor




user172009 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
















  • 1





    It's not absolutely clear what your intended result is. Are you looking for your final result to have later, earlier, and same columns? Or do you want three rows for each category, correspond to those three values. I recommend you edit in an example of the expected output, as that may make your question clearer.

    – RDFozz
    2 hours ago











  • are A and B fixed categories or can you change them?

    – seventyeightist
    2 hours ago














3












3








3








How can it be achieved in MS SQL 2016, when I need to always see every state under all existing categories even if there are no records, which satisfy the state formula?



Under a and b below I always want to see all three of later, earlier, and same with null counts whenever there is no corresponding record.



I guess it should be achievable with some sort of cross join?..



declare @t table (tid int not null identity(1,1) primary key clustered
,tcat char(1)
,tdat1 date
,tdat2 date
)

insert into @t select * from (values
('a', '2019-01-01', '2019-02-01')
,('a', '2019-02-01', '2019-01-01')
,('b', '2019-02-01', '2019-01-01')
,('b', '2019-01-01', '2019-01-01')
)as t(tcat, tdat1, tdat2)

select
tcat as category
,case
when tdat1 > tdat2 then 'later'
when tdat1 < tdat2 then 'earlier'
when tdat1 = tdat2 then 'same'
end as state
,count(1) as howmany
from @t
group by
tcat
,case
when tdat1 > tdat2 then 'later'
when tdat1 < tdat2 then 'earlier'
when tdat1 = tdat2 then 'same'
end









share|improve this question









New contributor




user172009 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












How can it be achieved in MS SQL 2016, when I need to always see every state under all existing categories even if there are no records, which satisfy the state formula?



Under a and b below I always want to see all three of later, earlier, and same with null counts whenever there is no corresponding record.



I guess it should be achievable with some sort of cross join?..



declare @t table (tid int not null identity(1,1) primary key clustered
,tcat char(1)
,tdat1 date
,tdat2 date
)

insert into @t select * from (values
('a', '2019-01-01', '2019-02-01')
,('a', '2019-02-01', '2019-01-01')
,('b', '2019-02-01', '2019-01-01')
,('b', '2019-01-01', '2019-01-01')
)as t(tcat, tdat1, tdat2)

select
tcat as category
,case
when tdat1 > tdat2 then 'later'
when tdat1 < tdat2 then 'earlier'
when tdat1 = tdat2 then 'same'
end as state
,count(1) as howmany
from @t
group by
tcat
,case
when tdat1 > tdat2 then 'later'
when tdat1 < tdat2 then 'earlier'
when tdat1 = tdat2 then 'same'
end






sql-server query






share|improve this question









New contributor




user172009 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




user172009 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 2 hours ago









Glorfindel

9201815




9201815






New contributor




user172009 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked 3 hours ago









user172009user172009

161




161




New contributor




user172009 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





user172009 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






user172009 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








  • 1





    It's not absolutely clear what your intended result is. Are you looking for your final result to have later, earlier, and same columns? Or do you want three rows for each category, correspond to those three values. I recommend you edit in an example of the expected output, as that may make your question clearer.

    – RDFozz
    2 hours ago











  • are A and B fixed categories or can you change them?

    – seventyeightist
    2 hours ago














  • 1





    It's not absolutely clear what your intended result is. Are you looking for your final result to have later, earlier, and same columns? Or do you want three rows for each category, correspond to those three values. I recommend you edit in an example of the expected output, as that may make your question clearer.

    – RDFozz
    2 hours ago











  • are A and B fixed categories or can you change them?

    – seventyeightist
    2 hours ago








1




1





It's not absolutely clear what your intended result is. Are you looking for your final result to have later, earlier, and same columns? Or do you want three rows for each category, correspond to those three values. I recommend you edit in an example of the expected output, as that may make your question clearer.

– RDFozz
2 hours ago





It's not absolutely clear what your intended result is. Are you looking for your final result to have later, earlier, and same columns? Or do you want three rows for each category, correspond to those three values. I recommend you edit in an example of the expected output, as that may make your question clearer.

– RDFozz
2 hours ago













are A and B fixed categories or can you change them?

– seventyeightist
2 hours ago





are A and B fixed categories or can you change them?

– seventyeightist
2 hours ago










3 Answers
3






active

oldest

votes


















3














If I understand your question correctly, here is one way to achieve your goal



--demo setup
declare @t table (tid int not null identity(1,1) primary key clustered
,tcat char(1)
,tdat1 date
,tdat2 date
)

insert into @t select * from (values
('a', '2019-01-01', '2019-02-01')
,('a', '2019-02-01', '2019-01-01')
,('b', '2019-02-01', '2019-01-01')
,('b', '2019-01-01', '2019-01-01')
)as t(tcat, tdat1, tdat2)

--the solution
;with BaseData as
(
select
tcat as category
,case
when tdat1 > tdat2 then 'later'
when tdat1 < tdat2 then 'earlier'
when tdat1 = tdat2 then 'same'
end as state
,count(1) as howmany
from @t
group by
tcat
,case
when tdat1 > tdat2 then 'later'
when tdat1 < tdat2 then 'earlier'
when tdat1 = tdat2 then 'same'
end
)
select * from BaseData
union
select tcat,'later' as state, 0 as howmany from @t t
where not exists(select * from basedata where category = t.tcat and state = 'later')
union
select tcat,'earlier' as state, 0 as howmany from @t t
where not exists(select * from basedata where category = t.tcat and state = 'earlier')
union
select tcat,'same' as state, 0 as howmany from @t t
where not exists(select * from basedata where category = t.tcat and state = 'same')




| category | state   | howmany |
|----------|---------|---------|
| a | earlier | 1 |
| a | later | 1 |
| a | same | 0 |
| b | earlier | 0 |
| b | later | 1 |
| b | same | 1 |





share|improve this answer































    3














    Here's a simple approach that uses CROSS JOIN to project all possible combinations of category and state, then OUTER JOIN to the data.



    declare @t table (tid int not null identity(1,1) primary key clustered
    ,tcat char(1)
    ,tdat1 date
    ,tdat2 date
    );

    insert into @t select * from (values
    ('a', '2019-01-01', '2019-02-01')
    ,('a', '2019-02-01', '2019-01-01')
    ,('b', '2019-02-01', '2019-01-01')
    ,('b', '2019-01-01', '2019-01-01')
    )as t(tcat, tdat1, tdat2);

    WITH t AS (
    SELECT
    tcat AS category,
    CASE
    WHEN tdat1 > tdat2 THEN 'later'
    WHEN tdat1 < tdat2 THEN 'earlier'
    WHEN tdat1 = tdat2 THEN 'same'
    END AS STATE,
    COUNT(1) AS howmany
    FROM @t
    GROUP BY
    tcat,
    CASE
    WHEN tdat1 > tdat2 THEN 'later'
    WHEN tdat1 < tdat2 THEN 'earlier'
    WHEN tdat1 = tdat2 THEN 'same'
    END
    )
    SELECT
    tcat.category,
    p.state,
    ISNULL(t.howmany, 0) AS howmany
    FROM (SELECT DISTINCT tcat AS category FROM @t) tcat
    CROSS JOIN (VALUES ('earlier'), ('same'), ('later')) p(state)
    LEFT OUTER JOIN t
    ON tcat.category = t.category
    AND p.state = t.state





    share|improve this answer































      1














      Another method (similar to @db2's answer):



      with
      grp as
      ( select
      tcat,
      sign(datediff(day, tdat2, tdat1)) as sgn,
      count(1) as howmany
      from @t
      group by
      tcat,
      sign(datediff(day, tdat2, tdat1))
      )
      select
      cat.tcat as category,
      st.state,
      coalesce(grp.howmany, 0) as howmany
      from
      ( values
      (-1, 'earlier'),
      ( 0, 'same'),
      (+1, 'later')
      ) as st (sgn, state)
      cross join
      ( select distinct tcat
      from @t
      ) as cat (tcat)
      left join grp
      on grp.sgn = st.sgn
      and grp.tcat = cat.tcat ;


      Test at dbfiddle.uk






      share|improve this answer























        Your Answer








        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "182"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: false,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: null,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });






        user172009 is a new contributor. Be nice, and check out our Code of Conduct.










        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f229172%2finclude-all-possible-values-of-sub-categories-under-each-category%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        3 Answers
        3






        active

        oldest

        votes








        3 Answers
        3






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        3














        If I understand your question correctly, here is one way to achieve your goal



        --demo setup
        declare @t table (tid int not null identity(1,1) primary key clustered
        ,tcat char(1)
        ,tdat1 date
        ,tdat2 date
        )

        insert into @t select * from (values
        ('a', '2019-01-01', '2019-02-01')
        ,('a', '2019-02-01', '2019-01-01')
        ,('b', '2019-02-01', '2019-01-01')
        ,('b', '2019-01-01', '2019-01-01')
        )as t(tcat, tdat1, tdat2)

        --the solution
        ;with BaseData as
        (
        select
        tcat as category
        ,case
        when tdat1 > tdat2 then 'later'
        when tdat1 < tdat2 then 'earlier'
        when tdat1 = tdat2 then 'same'
        end as state
        ,count(1) as howmany
        from @t
        group by
        tcat
        ,case
        when tdat1 > tdat2 then 'later'
        when tdat1 < tdat2 then 'earlier'
        when tdat1 = tdat2 then 'same'
        end
        )
        select * from BaseData
        union
        select tcat,'later' as state, 0 as howmany from @t t
        where not exists(select * from basedata where category = t.tcat and state = 'later')
        union
        select tcat,'earlier' as state, 0 as howmany from @t t
        where not exists(select * from basedata where category = t.tcat and state = 'earlier')
        union
        select tcat,'same' as state, 0 as howmany from @t t
        where not exists(select * from basedata where category = t.tcat and state = 'same')




        | category | state   | howmany |
        |----------|---------|---------|
        | a | earlier | 1 |
        | a | later | 1 |
        | a | same | 0 |
        | b | earlier | 0 |
        | b | later | 1 |
        | b | same | 1 |





        share|improve this answer




























          3














          If I understand your question correctly, here is one way to achieve your goal



          --demo setup
          declare @t table (tid int not null identity(1,1) primary key clustered
          ,tcat char(1)
          ,tdat1 date
          ,tdat2 date
          )

          insert into @t select * from (values
          ('a', '2019-01-01', '2019-02-01')
          ,('a', '2019-02-01', '2019-01-01')
          ,('b', '2019-02-01', '2019-01-01')
          ,('b', '2019-01-01', '2019-01-01')
          )as t(tcat, tdat1, tdat2)

          --the solution
          ;with BaseData as
          (
          select
          tcat as category
          ,case
          when tdat1 > tdat2 then 'later'
          when tdat1 < tdat2 then 'earlier'
          when tdat1 = tdat2 then 'same'
          end as state
          ,count(1) as howmany
          from @t
          group by
          tcat
          ,case
          when tdat1 > tdat2 then 'later'
          when tdat1 < tdat2 then 'earlier'
          when tdat1 = tdat2 then 'same'
          end
          )
          select * from BaseData
          union
          select tcat,'later' as state, 0 as howmany from @t t
          where not exists(select * from basedata where category = t.tcat and state = 'later')
          union
          select tcat,'earlier' as state, 0 as howmany from @t t
          where not exists(select * from basedata where category = t.tcat and state = 'earlier')
          union
          select tcat,'same' as state, 0 as howmany from @t t
          where not exists(select * from basedata where category = t.tcat and state = 'same')




          | category | state   | howmany |
          |----------|---------|---------|
          | a | earlier | 1 |
          | a | later | 1 |
          | a | same | 0 |
          | b | earlier | 0 |
          | b | later | 1 |
          | b | same | 1 |





          share|improve this answer


























            3












            3








            3







            If I understand your question correctly, here is one way to achieve your goal



            --demo setup
            declare @t table (tid int not null identity(1,1) primary key clustered
            ,tcat char(1)
            ,tdat1 date
            ,tdat2 date
            )

            insert into @t select * from (values
            ('a', '2019-01-01', '2019-02-01')
            ,('a', '2019-02-01', '2019-01-01')
            ,('b', '2019-02-01', '2019-01-01')
            ,('b', '2019-01-01', '2019-01-01')
            )as t(tcat, tdat1, tdat2)

            --the solution
            ;with BaseData as
            (
            select
            tcat as category
            ,case
            when tdat1 > tdat2 then 'later'
            when tdat1 < tdat2 then 'earlier'
            when tdat1 = tdat2 then 'same'
            end as state
            ,count(1) as howmany
            from @t
            group by
            tcat
            ,case
            when tdat1 > tdat2 then 'later'
            when tdat1 < tdat2 then 'earlier'
            when tdat1 = tdat2 then 'same'
            end
            )
            select * from BaseData
            union
            select tcat,'later' as state, 0 as howmany from @t t
            where not exists(select * from basedata where category = t.tcat and state = 'later')
            union
            select tcat,'earlier' as state, 0 as howmany from @t t
            where not exists(select * from basedata where category = t.tcat and state = 'earlier')
            union
            select tcat,'same' as state, 0 as howmany from @t t
            where not exists(select * from basedata where category = t.tcat and state = 'same')




            | category | state   | howmany |
            |----------|---------|---------|
            | a | earlier | 1 |
            | a | later | 1 |
            | a | same | 0 |
            | b | earlier | 0 |
            | b | later | 1 |
            | b | same | 1 |





            share|improve this answer













            If I understand your question correctly, here is one way to achieve your goal



            --demo setup
            declare @t table (tid int not null identity(1,1) primary key clustered
            ,tcat char(1)
            ,tdat1 date
            ,tdat2 date
            )

            insert into @t select * from (values
            ('a', '2019-01-01', '2019-02-01')
            ,('a', '2019-02-01', '2019-01-01')
            ,('b', '2019-02-01', '2019-01-01')
            ,('b', '2019-01-01', '2019-01-01')
            )as t(tcat, tdat1, tdat2)

            --the solution
            ;with BaseData as
            (
            select
            tcat as category
            ,case
            when tdat1 > tdat2 then 'later'
            when tdat1 < tdat2 then 'earlier'
            when tdat1 = tdat2 then 'same'
            end as state
            ,count(1) as howmany
            from @t
            group by
            tcat
            ,case
            when tdat1 > tdat2 then 'later'
            when tdat1 < tdat2 then 'earlier'
            when tdat1 = tdat2 then 'same'
            end
            )
            select * from BaseData
            union
            select tcat,'later' as state, 0 as howmany from @t t
            where not exists(select * from basedata where category = t.tcat and state = 'later')
            union
            select tcat,'earlier' as state, 0 as howmany from @t t
            where not exists(select * from basedata where category = t.tcat and state = 'earlier')
            union
            select tcat,'same' as state, 0 as howmany from @t t
            where not exists(select * from basedata where category = t.tcat and state = 'same')




            | category | state   | howmany |
            |----------|---------|---------|
            | a | earlier | 1 |
            | a | later | 1 |
            | a | same | 0 |
            | b | earlier | 0 |
            | b | later | 1 |
            | b | same | 1 |






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered 2 hours ago









            Scott HodginScott Hodgin

            17.2k21534




            17.2k21534

























                3














                Here's a simple approach that uses CROSS JOIN to project all possible combinations of category and state, then OUTER JOIN to the data.



                declare @t table (tid int not null identity(1,1) primary key clustered
                ,tcat char(1)
                ,tdat1 date
                ,tdat2 date
                );

                insert into @t select * from (values
                ('a', '2019-01-01', '2019-02-01')
                ,('a', '2019-02-01', '2019-01-01')
                ,('b', '2019-02-01', '2019-01-01')
                ,('b', '2019-01-01', '2019-01-01')
                )as t(tcat, tdat1, tdat2);

                WITH t AS (
                SELECT
                tcat AS category,
                CASE
                WHEN tdat1 > tdat2 THEN 'later'
                WHEN tdat1 < tdat2 THEN 'earlier'
                WHEN tdat1 = tdat2 THEN 'same'
                END AS STATE,
                COUNT(1) AS howmany
                FROM @t
                GROUP BY
                tcat,
                CASE
                WHEN tdat1 > tdat2 THEN 'later'
                WHEN tdat1 < tdat2 THEN 'earlier'
                WHEN tdat1 = tdat2 THEN 'same'
                END
                )
                SELECT
                tcat.category,
                p.state,
                ISNULL(t.howmany, 0) AS howmany
                FROM (SELECT DISTINCT tcat AS category FROM @t) tcat
                CROSS JOIN (VALUES ('earlier'), ('same'), ('later')) p(state)
                LEFT OUTER JOIN t
                ON tcat.category = t.category
                AND p.state = t.state





                share|improve this answer




























                  3














                  Here's a simple approach that uses CROSS JOIN to project all possible combinations of category and state, then OUTER JOIN to the data.



                  declare @t table (tid int not null identity(1,1) primary key clustered
                  ,tcat char(1)
                  ,tdat1 date
                  ,tdat2 date
                  );

                  insert into @t select * from (values
                  ('a', '2019-01-01', '2019-02-01')
                  ,('a', '2019-02-01', '2019-01-01')
                  ,('b', '2019-02-01', '2019-01-01')
                  ,('b', '2019-01-01', '2019-01-01')
                  )as t(tcat, tdat1, tdat2);

                  WITH t AS (
                  SELECT
                  tcat AS category,
                  CASE
                  WHEN tdat1 > tdat2 THEN 'later'
                  WHEN tdat1 < tdat2 THEN 'earlier'
                  WHEN tdat1 = tdat2 THEN 'same'
                  END AS STATE,
                  COUNT(1) AS howmany
                  FROM @t
                  GROUP BY
                  tcat,
                  CASE
                  WHEN tdat1 > tdat2 THEN 'later'
                  WHEN tdat1 < tdat2 THEN 'earlier'
                  WHEN tdat1 = tdat2 THEN 'same'
                  END
                  )
                  SELECT
                  tcat.category,
                  p.state,
                  ISNULL(t.howmany, 0) AS howmany
                  FROM (SELECT DISTINCT tcat AS category FROM @t) tcat
                  CROSS JOIN (VALUES ('earlier'), ('same'), ('later')) p(state)
                  LEFT OUTER JOIN t
                  ON tcat.category = t.category
                  AND p.state = t.state





                  share|improve this answer


























                    3












                    3








                    3







                    Here's a simple approach that uses CROSS JOIN to project all possible combinations of category and state, then OUTER JOIN to the data.



                    declare @t table (tid int not null identity(1,1) primary key clustered
                    ,tcat char(1)
                    ,tdat1 date
                    ,tdat2 date
                    );

                    insert into @t select * from (values
                    ('a', '2019-01-01', '2019-02-01')
                    ,('a', '2019-02-01', '2019-01-01')
                    ,('b', '2019-02-01', '2019-01-01')
                    ,('b', '2019-01-01', '2019-01-01')
                    )as t(tcat, tdat1, tdat2);

                    WITH t AS (
                    SELECT
                    tcat AS category,
                    CASE
                    WHEN tdat1 > tdat2 THEN 'later'
                    WHEN tdat1 < tdat2 THEN 'earlier'
                    WHEN tdat1 = tdat2 THEN 'same'
                    END AS STATE,
                    COUNT(1) AS howmany
                    FROM @t
                    GROUP BY
                    tcat,
                    CASE
                    WHEN tdat1 > tdat2 THEN 'later'
                    WHEN tdat1 < tdat2 THEN 'earlier'
                    WHEN tdat1 = tdat2 THEN 'same'
                    END
                    )
                    SELECT
                    tcat.category,
                    p.state,
                    ISNULL(t.howmany, 0) AS howmany
                    FROM (SELECT DISTINCT tcat AS category FROM @t) tcat
                    CROSS JOIN (VALUES ('earlier'), ('same'), ('later')) p(state)
                    LEFT OUTER JOIN t
                    ON tcat.category = t.category
                    AND p.state = t.state





                    share|improve this answer













                    Here's a simple approach that uses CROSS JOIN to project all possible combinations of category and state, then OUTER JOIN to the data.



                    declare @t table (tid int not null identity(1,1) primary key clustered
                    ,tcat char(1)
                    ,tdat1 date
                    ,tdat2 date
                    );

                    insert into @t select * from (values
                    ('a', '2019-01-01', '2019-02-01')
                    ,('a', '2019-02-01', '2019-01-01')
                    ,('b', '2019-02-01', '2019-01-01')
                    ,('b', '2019-01-01', '2019-01-01')
                    )as t(tcat, tdat1, tdat2);

                    WITH t AS (
                    SELECT
                    tcat AS category,
                    CASE
                    WHEN tdat1 > tdat2 THEN 'later'
                    WHEN tdat1 < tdat2 THEN 'earlier'
                    WHEN tdat1 = tdat2 THEN 'same'
                    END AS STATE,
                    COUNT(1) AS howmany
                    FROM @t
                    GROUP BY
                    tcat,
                    CASE
                    WHEN tdat1 > tdat2 THEN 'later'
                    WHEN tdat1 < tdat2 THEN 'earlier'
                    WHEN tdat1 = tdat2 THEN 'same'
                    END
                    )
                    SELECT
                    tcat.category,
                    p.state,
                    ISNULL(t.howmany, 0) AS howmany
                    FROM (SELECT DISTINCT tcat AS category FROM @t) tcat
                    CROSS JOIN (VALUES ('earlier'), ('same'), ('later')) p(state)
                    LEFT OUTER JOIN t
                    ON tcat.category = t.category
                    AND p.state = t.state






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered 2 hours ago









                    db2db2

                    8,08812448




                    8,08812448























                        1














                        Another method (similar to @db2's answer):



                        with
                        grp as
                        ( select
                        tcat,
                        sign(datediff(day, tdat2, tdat1)) as sgn,
                        count(1) as howmany
                        from @t
                        group by
                        tcat,
                        sign(datediff(day, tdat2, tdat1))
                        )
                        select
                        cat.tcat as category,
                        st.state,
                        coalesce(grp.howmany, 0) as howmany
                        from
                        ( values
                        (-1, 'earlier'),
                        ( 0, 'same'),
                        (+1, 'later')
                        ) as st (sgn, state)
                        cross join
                        ( select distinct tcat
                        from @t
                        ) as cat (tcat)
                        left join grp
                        on grp.sgn = st.sgn
                        and grp.tcat = cat.tcat ;


                        Test at dbfiddle.uk






                        share|improve this answer




























                          1














                          Another method (similar to @db2's answer):



                          with
                          grp as
                          ( select
                          tcat,
                          sign(datediff(day, tdat2, tdat1)) as sgn,
                          count(1) as howmany
                          from @t
                          group by
                          tcat,
                          sign(datediff(day, tdat2, tdat1))
                          )
                          select
                          cat.tcat as category,
                          st.state,
                          coalesce(grp.howmany, 0) as howmany
                          from
                          ( values
                          (-1, 'earlier'),
                          ( 0, 'same'),
                          (+1, 'later')
                          ) as st (sgn, state)
                          cross join
                          ( select distinct tcat
                          from @t
                          ) as cat (tcat)
                          left join grp
                          on grp.sgn = st.sgn
                          and grp.tcat = cat.tcat ;


                          Test at dbfiddle.uk






                          share|improve this answer


























                            1












                            1








                            1







                            Another method (similar to @db2's answer):



                            with
                            grp as
                            ( select
                            tcat,
                            sign(datediff(day, tdat2, tdat1)) as sgn,
                            count(1) as howmany
                            from @t
                            group by
                            tcat,
                            sign(datediff(day, tdat2, tdat1))
                            )
                            select
                            cat.tcat as category,
                            st.state,
                            coalesce(grp.howmany, 0) as howmany
                            from
                            ( values
                            (-1, 'earlier'),
                            ( 0, 'same'),
                            (+1, 'later')
                            ) as st (sgn, state)
                            cross join
                            ( select distinct tcat
                            from @t
                            ) as cat (tcat)
                            left join grp
                            on grp.sgn = st.sgn
                            and grp.tcat = cat.tcat ;


                            Test at dbfiddle.uk






                            share|improve this answer













                            Another method (similar to @db2's answer):



                            with
                            grp as
                            ( select
                            tcat,
                            sign(datediff(day, tdat2, tdat1)) as sgn,
                            count(1) as howmany
                            from @t
                            group by
                            tcat,
                            sign(datediff(day, tdat2, tdat1))
                            )
                            select
                            cat.tcat as category,
                            st.state,
                            coalesce(grp.howmany, 0) as howmany
                            from
                            ( values
                            (-1, 'earlier'),
                            ( 0, 'same'),
                            (+1, 'later')
                            ) as st (sgn, state)
                            cross join
                            ( select distinct tcat
                            from @t
                            ) as cat (tcat)
                            left join grp
                            on grp.sgn = st.sgn
                            and grp.tcat = cat.tcat ;


                            Test at dbfiddle.uk







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered 1 hour ago









                            ypercubeᵀᴹypercubeᵀᴹ

                            75.8k11128211




                            75.8k11128211






















                                user172009 is a new contributor. Be nice, and check out our Code of Conduct.










                                draft saved

                                draft discarded


















                                user172009 is a new contributor. Be nice, and check out our Code of Conduct.













                                user172009 is a new contributor. Be nice, and check out our Code of Conduct.












                                user172009 is a new contributor. Be nice, and check out our Code of Conduct.
















                                Thanks for contributing an answer to Database Administrators Stack Exchange!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f229172%2finclude-all-possible-values-of-sub-categories-under-each-category%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                Callistus I

                                Tabula Rosettana

                                How to label and detect the document text images