Include all possible values of sub-categories under each category

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












2















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



















  • 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
    Feb 7 at 21:27











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

    – seventyeightist
    Feb 7 at 21:45















2















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



















  • 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
    Feb 7 at 21:27











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

    – seventyeightist
    Feb 7 at 21:45













2












2








2


0






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
















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















share|improve this question













share|improve this question




share|improve this question








edited Feb 7 at 21:22









Glorfindel

1,0011816




1,0011816










asked Feb 7 at 19:56









user172009user172009

141




141







  • 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
    Feb 7 at 21:27











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

    – seventyeightist
    Feb 7 at 21:45












  • 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
    Feb 7 at 21:27











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

    – seventyeightist
    Feb 7 at 21:45







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
Feb 7 at 21:27





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
Feb 7 at 21:27













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

– seventyeightist
Feb 7 at 21:45





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

– seventyeightist
Feb 7 at 21:45










4 Answers
4






active

oldest

votes


















4














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






























    4














    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














      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














        Depending on how you want to display your results, you can use PIVOT or UNPIVOT to present "same, earlier, later" as columns or rows:



        More info: PIVOT



        Columns:



        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 category,
        COALESCE(pvt.later, 0) AS later,
        COALESCE(pvt.earlier, 0) AS earlier,
        COALESCE(pvt.same, 0) AS same
        FROM
        (
        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
        ) src
        PIVOT
        (
        SUM(howmany) FOR [state] IN ([later], [earlier], [same])
        ) pvt


        Output:



        category later earlier same
        --------------------------------
        a 1 1 0
        b 1 0 1


        Rows:



        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 *
        FROM
        (
        SELECT category,
        COALESCE(pvt.later, 0) AS later,
        COALESCE(pvt.earlier, 0) AS earlier,
        COALESCE(pvt.same, 0) AS same
        FROM
        (
        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
        ) src
        PIVOT
        (
        SUM(howmany) FOR [state] IN ([later], [earlier], [same])
        ) pvt
        )src
        UNPIVOT
        (
        Howmany for State IN ([later], [earlier], [same])
        ) upv


        Output:



        category Howmany State
        ------------------------
        a 1 later
        a 1 earlier
        a 0 same
        b 1 later
        b 0 earlier
        b 1 same





        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
          );



          );













          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

























          4 Answers
          4






          active

          oldest

          votes








          4 Answers
          4






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          4














          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



























            4














            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

























              4












              4








              4







              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 Feb 7 at 21:30









              Scott HodginScott Hodgin

              17.5k21634




              17.5k21634























                  4














                  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



























                    4














                    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

























                      4












                      4








                      4







                      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 Feb 7 at 21:51









                      db2db2

                      8,14012448




                      8,14012448





















                          3














                          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



























                            3














                            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

























                              3












                              3








                              3







                              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 Feb 7 at 21:55









                              ypercubeᵀᴹypercubeᵀᴹ

                              77.1k11134215




                              77.1k11134215





















                                  1














                                  Depending on how you want to display your results, you can use PIVOT or UNPIVOT to present "same, earlier, later" as columns or rows:



                                  More info: PIVOT



                                  Columns:



                                  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 category,
                                  COALESCE(pvt.later, 0) AS later,
                                  COALESCE(pvt.earlier, 0) AS earlier,
                                  COALESCE(pvt.same, 0) AS same
                                  FROM
                                  (
                                  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
                                  ) src
                                  PIVOT
                                  (
                                  SUM(howmany) FOR [state] IN ([later], [earlier], [same])
                                  ) pvt


                                  Output:



                                  category later earlier same
                                  --------------------------------
                                  a 1 1 0
                                  b 1 0 1


                                  Rows:



                                  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 *
                                  FROM
                                  (
                                  SELECT category,
                                  COALESCE(pvt.later, 0) AS later,
                                  COALESCE(pvt.earlier, 0) AS earlier,
                                  COALESCE(pvt.same, 0) AS same
                                  FROM
                                  (
                                  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
                                  ) src
                                  PIVOT
                                  (
                                  SUM(howmany) FOR [state] IN ([later], [earlier], [same])
                                  ) pvt
                                  )src
                                  UNPIVOT
                                  (
                                  Howmany for State IN ([later], [earlier], [same])
                                  ) upv


                                  Output:



                                  category Howmany State
                                  ------------------------
                                  a 1 later
                                  a 1 earlier
                                  a 0 same
                                  b 1 later
                                  b 0 earlier
                                  b 1 same





                                  share|improve this answer



























                                    1














                                    Depending on how you want to display your results, you can use PIVOT or UNPIVOT to present "same, earlier, later" as columns or rows:



                                    More info: PIVOT



                                    Columns:



                                    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 category,
                                    COALESCE(pvt.later, 0) AS later,
                                    COALESCE(pvt.earlier, 0) AS earlier,
                                    COALESCE(pvt.same, 0) AS same
                                    FROM
                                    (
                                    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
                                    ) src
                                    PIVOT
                                    (
                                    SUM(howmany) FOR [state] IN ([later], [earlier], [same])
                                    ) pvt


                                    Output:



                                    category later earlier same
                                    --------------------------------
                                    a 1 1 0
                                    b 1 0 1


                                    Rows:



                                    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 *
                                    FROM
                                    (
                                    SELECT category,
                                    COALESCE(pvt.later, 0) AS later,
                                    COALESCE(pvt.earlier, 0) AS earlier,
                                    COALESCE(pvt.same, 0) AS same
                                    FROM
                                    (
                                    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
                                    ) src
                                    PIVOT
                                    (
                                    SUM(howmany) FOR [state] IN ([later], [earlier], [same])
                                    ) pvt
                                    )src
                                    UNPIVOT
                                    (
                                    Howmany for State IN ([later], [earlier], [same])
                                    ) upv


                                    Output:



                                    category Howmany State
                                    ------------------------
                                    a 1 later
                                    a 1 earlier
                                    a 0 same
                                    b 1 later
                                    b 0 earlier
                                    b 1 same





                                    share|improve this answer

























                                      1












                                      1








                                      1







                                      Depending on how you want to display your results, you can use PIVOT or UNPIVOT to present "same, earlier, later" as columns or rows:



                                      More info: PIVOT



                                      Columns:



                                      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 category,
                                      COALESCE(pvt.later, 0) AS later,
                                      COALESCE(pvt.earlier, 0) AS earlier,
                                      COALESCE(pvt.same, 0) AS same
                                      FROM
                                      (
                                      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
                                      ) src
                                      PIVOT
                                      (
                                      SUM(howmany) FOR [state] IN ([later], [earlier], [same])
                                      ) pvt


                                      Output:



                                      category later earlier same
                                      --------------------------------
                                      a 1 1 0
                                      b 1 0 1


                                      Rows:



                                      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 *
                                      FROM
                                      (
                                      SELECT category,
                                      COALESCE(pvt.later, 0) AS later,
                                      COALESCE(pvt.earlier, 0) AS earlier,
                                      COALESCE(pvt.same, 0) AS same
                                      FROM
                                      (
                                      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
                                      ) src
                                      PIVOT
                                      (
                                      SUM(howmany) FOR [state] IN ([later], [earlier], [same])
                                      ) pvt
                                      )src
                                      UNPIVOT
                                      (
                                      Howmany for State IN ([later], [earlier], [same])
                                      ) upv


                                      Output:



                                      category Howmany State
                                      ------------------------
                                      a 1 later
                                      a 1 earlier
                                      a 0 same
                                      b 1 later
                                      b 0 earlier
                                      b 1 same





                                      share|improve this answer













                                      Depending on how you want to display your results, you can use PIVOT or UNPIVOT to present "same, earlier, later" as columns or rows:



                                      More info: PIVOT



                                      Columns:



                                      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 category,
                                      COALESCE(pvt.later, 0) AS later,
                                      COALESCE(pvt.earlier, 0) AS earlier,
                                      COALESCE(pvt.same, 0) AS same
                                      FROM
                                      (
                                      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
                                      ) src
                                      PIVOT
                                      (
                                      SUM(howmany) FOR [state] IN ([later], [earlier], [same])
                                      ) pvt


                                      Output:



                                      category later earlier same
                                      --------------------------------
                                      a 1 1 0
                                      b 1 0 1


                                      Rows:



                                      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 *
                                      FROM
                                      (
                                      SELECT category,
                                      COALESCE(pvt.later, 0) AS later,
                                      COALESCE(pvt.earlier, 0) AS earlier,
                                      COALESCE(pvt.same, 0) AS same
                                      FROM
                                      (
                                      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
                                      ) src
                                      PIVOT
                                      (
                                      SUM(howmany) FOR [state] IN ([later], [earlier], [same])
                                      ) pvt
                                      )src
                                      UNPIVOT
                                      (
                                      Howmany for State IN ([later], [earlier], [same])
                                      ) upv


                                      Output:



                                      category Howmany State
                                      ------------------------
                                      a 1 later
                                      a 1 earlier
                                      a 0 same
                                      b 1 later
                                      b 0 earlier
                                      b 1 same






                                      share|improve this answer












                                      share|improve this answer



                                      share|improve this answer










                                      answered Feb 8 at 8:15









                                      HandyDHandyD

                                      1,069212




                                      1,069212



























                                          draft saved

                                          draft discarded
















































                                          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

                                          How to check contact read email or not when send email to Individual?

                                          Displaying single band from multi-band raster using QGIS

                                          How many registers does an x86_64 CPU actually have?