How to fill value as zero when No data exists for particular week in oracle










1















I have a table with following structure.



Note_title varchar2(100)
Note_created_on date


Now in a report, I want to show all notes created week-wise, So I implemented the following solution for it.



SELECT to_char(Note_created_on - 7/24,'ww')||'/'||to_char(Note_created_on - 7/24,'yyyy') as Week ,
nvl(COUNT(Note_title),'0') as AMOUNT
FROM Notes
GROUP BY to_char(Note_created_on - 7/24,'ww') ,
to_char(Note_created_on -7/24,'yyyy')
ORDER BY to_char(Note_created_on - 7/24,'ww') DESC


And i am getting correct output from it, But suppose week 42,45 do not have any created Note then its just missing it.
Sample Output:



WEEK AMOUNT
46/2018 3
44/2018 22
43/2018 45
41/2018 1
40/2018 2
39/2018 27
38/2018 23


So How can I get zero values for week 42,45 instead of leaving them out?










share|improve this question



















  • 2





    Have a calendar table that stores all possible weeks. Outer join.

    – jarlh
    Nov 14 '18 at 10:10











  • Can you please share any example?

    – Ekaz
    Nov 14 '18 at 10:12















1















I have a table with following structure.



Note_title varchar2(100)
Note_created_on date


Now in a report, I want to show all notes created week-wise, So I implemented the following solution for it.



SELECT to_char(Note_created_on - 7/24,'ww')||'/'||to_char(Note_created_on - 7/24,'yyyy') as Week ,
nvl(COUNT(Note_title),'0') as AMOUNT
FROM Notes
GROUP BY to_char(Note_created_on - 7/24,'ww') ,
to_char(Note_created_on -7/24,'yyyy')
ORDER BY to_char(Note_created_on - 7/24,'ww') DESC


And i am getting correct output from it, But suppose week 42,45 do not have any created Note then its just missing it.
Sample Output:



WEEK AMOUNT
46/2018 3
44/2018 22
43/2018 45
41/2018 1
40/2018 2
39/2018 27
38/2018 23


So How can I get zero values for week 42,45 instead of leaving them out?










share|improve this question



















  • 2





    Have a calendar table that stores all possible weeks. Outer join.

    – jarlh
    Nov 14 '18 at 10:10











  • Can you please share any example?

    – Ekaz
    Nov 14 '18 at 10:12













1












1








1








I have a table with following structure.



Note_title varchar2(100)
Note_created_on date


Now in a report, I want to show all notes created week-wise, So I implemented the following solution for it.



SELECT to_char(Note_created_on - 7/24,'ww')||'/'||to_char(Note_created_on - 7/24,'yyyy') as Week ,
nvl(COUNT(Note_title),'0') as AMOUNT
FROM Notes
GROUP BY to_char(Note_created_on - 7/24,'ww') ,
to_char(Note_created_on -7/24,'yyyy')
ORDER BY to_char(Note_created_on - 7/24,'ww') DESC


And i am getting correct output from it, But suppose week 42,45 do not have any created Note then its just missing it.
Sample Output:



WEEK AMOUNT
46/2018 3
44/2018 22
43/2018 45
41/2018 1
40/2018 2
39/2018 27
38/2018 23


So How can I get zero values for week 42,45 instead of leaving them out?










share|improve this question
















I have a table with following structure.



Note_title varchar2(100)
Note_created_on date


Now in a report, I want to show all notes created week-wise, So I implemented the following solution for it.



SELECT to_char(Note_created_on - 7/24,'ww')||'/'||to_char(Note_created_on - 7/24,'yyyy') as Week ,
nvl(COUNT(Note_title),'0') as AMOUNT
FROM Notes
GROUP BY to_char(Note_created_on - 7/24,'ww') ,
to_char(Note_created_on -7/24,'yyyy')
ORDER BY to_char(Note_created_on - 7/24,'ww') DESC


And i am getting correct output from it, But suppose week 42,45 do not have any created Note then its just missing it.
Sample Output:



WEEK AMOUNT
46/2018 3
44/2018 22
43/2018 45
41/2018 1
40/2018 2
39/2018 27
38/2018 23


So How can I get zero values for week 42,45 instead of leaving them out?







sql oracle plsql






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 10:10









D.Mendes

11810




11810










asked Nov 14 '18 at 10:08









EkazEkaz

374




374







  • 2





    Have a calendar table that stores all possible weeks. Outer join.

    – jarlh
    Nov 14 '18 at 10:10











  • Can you please share any example?

    – Ekaz
    Nov 14 '18 at 10:12












  • 2





    Have a calendar table that stores all possible weeks. Outer join.

    – jarlh
    Nov 14 '18 at 10:10











  • Can you please share any example?

    – Ekaz
    Nov 14 '18 at 10:12







2




2





Have a calendar table that stores all possible weeks. Outer join.

– jarlh
Nov 14 '18 at 10:10





Have a calendar table that stores all possible weeks. Outer join.

– jarlh
Nov 14 '18 at 10:10













Can you please share any example?

– Ekaz
Nov 14 '18 at 10:12





Can you please share any example?

– Ekaz
Nov 14 '18 at 10:12












3 Answers
3






active

oldest

votes


















0














First you would need to generate all the weeks between each year, after that would left join with the Notes tables on the weeks and group by the weeks generated. Eg:



 with weeks
as ( select level as lvl /*Assume 52 weeks in a calendar year..*/
from dual
connect by level <=52
)
,weeks_year
as (select distinct
b.lvl||'/'||trunc(Note_created_on,'YYYY') as week_year_val /*From the start of year in Note_created_on*/
from Notes a
join weeks b
on 1=1
)
SELECT a.week_year_val as Week
,COUNT(Note_title) as AMOUNT
FROM weeks_year a
LEFT JOIN Notes b
ON a.week_year_val=to_char(b.Note_created_on - 7/24,'ww')||'/'||to_char(b.Note_created_on - 7/24,'yyyy')
GROUP BY a.week_year_val
ORDER BY a.week_year_val DESC





share|improve this answer






























    0














    If you want to perform this for the current year, you may use the following SQL statement which uses such a RIGHT JOIN as below :



    SELECT d.week as Week,
    nvl(COUNT(Note_title), '0') as AMOUNT
    FROM Notes
    RIGHT JOIN
    (SELECT lpad(level,2,'0')|| '/' ||to_char(sysdate,'yyyy') as week,
    '0' as amount FROM dual CONNECT BY level <= 53) d
    ON
    ( d.week =
    to_char(Note_created_on - 7 / 24, 'ww') ||'/'||to_char(Note_created_on - 7 / 24, 'yyyy') )
    GROUP BY d.week
    ORDER BY d.week DESC;


    P.S. There's a common belief that a year is composed of 52 weeks, true but truncated :). So, I used 53,



    Notice that select to_char( date'2016-12-31' - 7 / 24, 'ww') from dual yields 53 as a sample.



    Rextester Demo






    share|improve this answer
































      0














      As mentioned by jarlh:



      Create a list of weeks:



      SELECT TO_CHAR(LEVEL, 'FM00')||'/2018' wk
      FROM dual
      CONNECT BY LEVEL <= 53


      This query generates 53 rows, and level is just a number.. 1.. 2.. upto 53. We format it to become 01/2018, 02/2018.. 53/2018



      If you plan to use this query in other years, you'd be better off making the year dynamic:



      SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
      FROM dual
      CONNECT BY LEVEL <= 53


      (Credits to Barbaros for pointing out that the last day of any year is reported by Oracle as being in week 53, or said another way 7*52 = 364)



      We left join the notes data onto it. I wasn't really clear on why you subtracted 7 hours from the date (time zone?) but I left it. I removed the complexity of the count, as you seem to only want the count of records in a particular week. I also removed the double to_char, because you can do it all in a single operation. One doesn't need to TO_CHAR(date, 'WW')||'/'||TO_CHAR(date,'YYYY') etc.. you just tochar with WW/YYYY as a format. Our query now looks like:



      SELECT lst.wk as week, COALESCE(amt, 0) as amount FROM
      (
      SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
      FROM dual
      CONNECT BY LEVEL <= 52
      ) lst
      LEFT OUTER JOIN
      (
      SELECT
      to_char(Note_created_on - 7/24,'ww/yyyy') as wk,
      COUNT(*) as amt
      FROM Notes
      GROUP BY to_char(Note_created_on - 7/24,'ww/yyyy')
      ) dat
      ON lst.wk = dat.wk
      ORDER BY lst.wk


      For weeks where there are no note, the left join records a null against that week, so we coalesce it to make it 0.



      You can, of course, do the query in other ways (many ways), here's a compare:



      SELECT lst.wk as week, COUNT(dat.wk) as amount FROM
      (
      SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
      FROM dual
      CONNECT BY LEVEL <= 52
      ) lst
      LEFT OUTER JOIN
      (
      SELECT
      to_char(Note_created_on - 7/24,'ww/yyyy') as wk
      FROM Notes
      ) dat
      ON lst.wk = dat.wk
      GROUP BY lst.wk
      ORDER BY lst.wk


      In this form we do the groupby/count after the join. By counting the dat.wk, which for some lst.wk might be NULL, we can omit the coalesce, because count(null) is 0






      share|improve this answer
























        Your Answer






        StackExchange.ifUsing("editor", function ()
        StackExchange.using("externalEditor", function ()
        StackExchange.using("snippets", function ()
        StackExchange.snippets.init();
        );
        );
        , "code-snippets");

        StackExchange.ready(function()
        var channelOptions =
        tags: "".split(" "),
        id: "1"
        ;
        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: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        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%2fstackoverflow.com%2fquestions%2f53297631%2fhow-to-fill-value-as-zero-when-no-data-exists-for-particular-week-in-oracle%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









        0














        First you would need to generate all the weeks between each year, after that would left join with the Notes tables on the weeks and group by the weeks generated. Eg:



         with weeks
        as ( select level as lvl /*Assume 52 weeks in a calendar year..*/
        from dual
        connect by level <=52
        )
        ,weeks_year
        as (select distinct
        b.lvl||'/'||trunc(Note_created_on,'YYYY') as week_year_val /*From the start of year in Note_created_on*/
        from Notes a
        join weeks b
        on 1=1
        )
        SELECT a.week_year_val as Week
        ,COUNT(Note_title) as AMOUNT
        FROM weeks_year a
        LEFT JOIN Notes b
        ON a.week_year_val=to_char(b.Note_created_on - 7/24,'ww')||'/'||to_char(b.Note_created_on - 7/24,'yyyy')
        GROUP BY a.week_year_val
        ORDER BY a.week_year_val DESC





        share|improve this answer



























          0














          First you would need to generate all the weeks between each year, after that would left join with the Notes tables on the weeks and group by the weeks generated. Eg:



           with weeks
          as ( select level as lvl /*Assume 52 weeks in a calendar year..*/
          from dual
          connect by level <=52
          )
          ,weeks_year
          as (select distinct
          b.lvl||'/'||trunc(Note_created_on,'YYYY') as week_year_val /*From the start of year in Note_created_on*/
          from Notes a
          join weeks b
          on 1=1
          )
          SELECT a.week_year_val as Week
          ,COUNT(Note_title) as AMOUNT
          FROM weeks_year a
          LEFT JOIN Notes b
          ON a.week_year_val=to_char(b.Note_created_on - 7/24,'ww')||'/'||to_char(b.Note_created_on - 7/24,'yyyy')
          GROUP BY a.week_year_val
          ORDER BY a.week_year_val DESC





          share|improve this answer

























            0












            0








            0







            First you would need to generate all the weeks between each year, after that would left join with the Notes tables on the weeks and group by the weeks generated. Eg:



             with weeks
            as ( select level as lvl /*Assume 52 weeks in a calendar year..*/
            from dual
            connect by level <=52
            )
            ,weeks_year
            as (select distinct
            b.lvl||'/'||trunc(Note_created_on,'YYYY') as week_year_val /*From the start of year in Note_created_on*/
            from Notes a
            join weeks b
            on 1=1
            )
            SELECT a.week_year_val as Week
            ,COUNT(Note_title) as AMOUNT
            FROM weeks_year a
            LEFT JOIN Notes b
            ON a.week_year_val=to_char(b.Note_created_on - 7/24,'ww')||'/'||to_char(b.Note_created_on - 7/24,'yyyy')
            GROUP BY a.week_year_val
            ORDER BY a.week_year_val DESC





            share|improve this answer













            First you would need to generate all the weeks between each year, after that would left join with the Notes tables on the weeks and group by the weeks generated. Eg:



             with weeks
            as ( select level as lvl /*Assume 52 weeks in a calendar year..*/
            from dual
            connect by level <=52
            )
            ,weeks_year
            as (select distinct
            b.lvl||'/'||trunc(Note_created_on,'YYYY') as week_year_val /*From the start of year in Note_created_on*/
            from Notes a
            join weeks b
            on 1=1
            )
            SELECT a.week_year_val as Week
            ,COUNT(Note_title) as AMOUNT
            FROM weeks_year a
            LEFT JOIN Notes b
            ON a.week_year_val=to_char(b.Note_created_on - 7/24,'ww')||'/'||to_char(b.Note_created_on - 7/24,'yyyy')
            GROUP BY a.week_year_val
            ORDER BY a.week_year_val DESC






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 14 '18 at 10:32









            George JosephGeorge Joseph

            1,59059




            1,59059























                0














                If you want to perform this for the current year, you may use the following SQL statement which uses such a RIGHT JOIN as below :



                SELECT d.week as Week,
                nvl(COUNT(Note_title), '0') as AMOUNT
                FROM Notes
                RIGHT JOIN
                (SELECT lpad(level,2,'0')|| '/' ||to_char(sysdate,'yyyy') as week,
                '0' as amount FROM dual CONNECT BY level <= 53) d
                ON
                ( d.week =
                to_char(Note_created_on - 7 / 24, 'ww') ||'/'||to_char(Note_created_on - 7 / 24, 'yyyy') )
                GROUP BY d.week
                ORDER BY d.week DESC;


                P.S. There's a common belief that a year is composed of 52 weeks, true but truncated :). So, I used 53,



                Notice that select to_char( date'2016-12-31' - 7 / 24, 'ww') from dual yields 53 as a sample.



                Rextester Demo






                share|improve this answer





























                  0














                  If you want to perform this for the current year, you may use the following SQL statement which uses such a RIGHT JOIN as below :



                  SELECT d.week as Week,
                  nvl(COUNT(Note_title), '0') as AMOUNT
                  FROM Notes
                  RIGHT JOIN
                  (SELECT lpad(level,2,'0')|| '/' ||to_char(sysdate,'yyyy') as week,
                  '0' as amount FROM dual CONNECT BY level <= 53) d
                  ON
                  ( d.week =
                  to_char(Note_created_on - 7 / 24, 'ww') ||'/'||to_char(Note_created_on - 7 / 24, 'yyyy') )
                  GROUP BY d.week
                  ORDER BY d.week DESC;


                  P.S. There's a common belief that a year is composed of 52 weeks, true but truncated :). So, I used 53,



                  Notice that select to_char( date'2016-12-31' - 7 / 24, 'ww') from dual yields 53 as a sample.



                  Rextester Demo






                  share|improve this answer



























                    0












                    0








                    0







                    If you want to perform this for the current year, you may use the following SQL statement which uses such a RIGHT JOIN as below :



                    SELECT d.week as Week,
                    nvl(COUNT(Note_title), '0') as AMOUNT
                    FROM Notes
                    RIGHT JOIN
                    (SELECT lpad(level,2,'0')|| '/' ||to_char(sysdate,'yyyy') as week,
                    '0' as amount FROM dual CONNECT BY level <= 53) d
                    ON
                    ( d.week =
                    to_char(Note_created_on - 7 / 24, 'ww') ||'/'||to_char(Note_created_on - 7 / 24, 'yyyy') )
                    GROUP BY d.week
                    ORDER BY d.week DESC;


                    P.S. There's a common belief that a year is composed of 52 weeks, true but truncated :). So, I used 53,



                    Notice that select to_char( date'2016-12-31' - 7 / 24, 'ww') from dual yields 53 as a sample.



                    Rextester Demo






                    share|improve this answer















                    If you want to perform this for the current year, you may use the following SQL statement which uses such a RIGHT JOIN as below :



                    SELECT d.week as Week,
                    nvl(COUNT(Note_title), '0') as AMOUNT
                    FROM Notes
                    RIGHT JOIN
                    (SELECT lpad(level,2,'0')|| '/' ||to_char(sysdate,'yyyy') as week,
                    '0' as amount FROM dual CONNECT BY level <= 53) d
                    ON
                    ( d.week =
                    to_char(Note_created_on - 7 / 24, 'ww') ||'/'||to_char(Note_created_on - 7 / 24, 'yyyy') )
                    GROUP BY d.week
                    ORDER BY d.week DESC;


                    P.S. There's a common belief that a year is composed of 52 weeks, true but truncated :). So, I used 53,



                    Notice that select to_char( date'2016-12-31' - 7 / 24, 'ww') from dual yields 53 as a sample.



                    Rextester Demo







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Nov 14 '18 at 10:39

























                    answered Nov 14 '18 at 10:32









                    Barbaros ÖzhanBarbaros Özhan

                    14k71634




                    14k71634





















                        0














                        As mentioned by jarlh:



                        Create a list of weeks:



                        SELECT TO_CHAR(LEVEL, 'FM00')||'/2018' wk
                        FROM dual
                        CONNECT BY LEVEL <= 53


                        This query generates 53 rows, and level is just a number.. 1.. 2.. upto 53. We format it to become 01/2018, 02/2018.. 53/2018



                        If you plan to use this query in other years, you'd be better off making the year dynamic:



                        SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
                        FROM dual
                        CONNECT BY LEVEL <= 53


                        (Credits to Barbaros for pointing out that the last day of any year is reported by Oracle as being in week 53, or said another way 7*52 = 364)



                        We left join the notes data onto it. I wasn't really clear on why you subtracted 7 hours from the date (time zone?) but I left it. I removed the complexity of the count, as you seem to only want the count of records in a particular week. I also removed the double to_char, because you can do it all in a single operation. One doesn't need to TO_CHAR(date, 'WW')||'/'||TO_CHAR(date,'YYYY') etc.. you just tochar with WW/YYYY as a format. Our query now looks like:



                        SELECT lst.wk as week, COALESCE(amt, 0) as amount FROM
                        (
                        SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
                        FROM dual
                        CONNECT BY LEVEL <= 52
                        ) lst
                        LEFT OUTER JOIN
                        (
                        SELECT
                        to_char(Note_created_on - 7/24,'ww/yyyy') as wk,
                        COUNT(*) as amt
                        FROM Notes
                        GROUP BY to_char(Note_created_on - 7/24,'ww/yyyy')
                        ) dat
                        ON lst.wk = dat.wk
                        ORDER BY lst.wk


                        For weeks where there are no note, the left join records a null against that week, so we coalesce it to make it 0.



                        You can, of course, do the query in other ways (many ways), here's a compare:



                        SELECT lst.wk as week, COUNT(dat.wk) as amount FROM
                        (
                        SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
                        FROM dual
                        CONNECT BY LEVEL <= 52
                        ) lst
                        LEFT OUTER JOIN
                        (
                        SELECT
                        to_char(Note_created_on - 7/24,'ww/yyyy') as wk
                        FROM Notes
                        ) dat
                        ON lst.wk = dat.wk
                        GROUP BY lst.wk
                        ORDER BY lst.wk


                        In this form we do the groupby/count after the join. By counting the dat.wk, which for some lst.wk might be NULL, we can omit the coalesce, because count(null) is 0






                        share|improve this answer





























                          0














                          As mentioned by jarlh:



                          Create a list of weeks:



                          SELECT TO_CHAR(LEVEL, 'FM00')||'/2018' wk
                          FROM dual
                          CONNECT BY LEVEL <= 53


                          This query generates 53 rows, and level is just a number.. 1.. 2.. upto 53. We format it to become 01/2018, 02/2018.. 53/2018



                          If you plan to use this query in other years, you'd be better off making the year dynamic:



                          SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
                          FROM dual
                          CONNECT BY LEVEL <= 53


                          (Credits to Barbaros for pointing out that the last day of any year is reported by Oracle as being in week 53, or said another way 7*52 = 364)



                          We left join the notes data onto it. I wasn't really clear on why you subtracted 7 hours from the date (time zone?) but I left it. I removed the complexity of the count, as you seem to only want the count of records in a particular week. I also removed the double to_char, because you can do it all in a single operation. One doesn't need to TO_CHAR(date, 'WW')||'/'||TO_CHAR(date,'YYYY') etc.. you just tochar with WW/YYYY as a format. Our query now looks like:



                          SELECT lst.wk as week, COALESCE(amt, 0) as amount FROM
                          (
                          SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
                          FROM dual
                          CONNECT BY LEVEL <= 52
                          ) lst
                          LEFT OUTER JOIN
                          (
                          SELECT
                          to_char(Note_created_on - 7/24,'ww/yyyy') as wk,
                          COUNT(*) as amt
                          FROM Notes
                          GROUP BY to_char(Note_created_on - 7/24,'ww/yyyy')
                          ) dat
                          ON lst.wk = dat.wk
                          ORDER BY lst.wk


                          For weeks where there are no note, the left join records a null against that week, so we coalesce it to make it 0.



                          You can, of course, do the query in other ways (many ways), here's a compare:



                          SELECT lst.wk as week, COUNT(dat.wk) as amount FROM
                          (
                          SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
                          FROM dual
                          CONNECT BY LEVEL <= 52
                          ) lst
                          LEFT OUTER JOIN
                          (
                          SELECT
                          to_char(Note_created_on - 7/24,'ww/yyyy') as wk
                          FROM Notes
                          ) dat
                          ON lst.wk = dat.wk
                          GROUP BY lst.wk
                          ORDER BY lst.wk


                          In this form we do the groupby/count after the join. By counting the dat.wk, which for some lst.wk might be NULL, we can omit the coalesce, because count(null) is 0






                          share|improve this answer



























                            0












                            0








                            0







                            As mentioned by jarlh:



                            Create a list of weeks:



                            SELECT TO_CHAR(LEVEL, 'FM00')||'/2018' wk
                            FROM dual
                            CONNECT BY LEVEL <= 53


                            This query generates 53 rows, and level is just a number.. 1.. 2.. upto 53. We format it to become 01/2018, 02/2018.. 53/2018



                            If you plan to use this query in other years, you'd be better off making the year dynamic:



                            SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
                            FROM dual
                            CONNECT BY LEVEL <= 53


                            (Credits to Barbaros for pointing out that the last day of any year is reported by Oracle as being in week 53, or said another way 7*52 = 364)



                            We left join the notes data onto it. I wasn't really clear on why you subtracted 7 hours from the date (time zone?) but I left it. I removed the complexity of the count, as you seem to only want the count of records in a particular week. I also removed the double to_char, because you can do it all in a single operation. One doesn't need to TO_CHAR(date, 'WW')||'/'||TO_CHAR(date,'YYYY') etc.. you just tochar with WW/YYYY as a format. Our query now looks like:



                            SELECT lst.wk as week, COALESCE(amt, 0) as amount FROM
                            (
                            SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
                            FROM dual
                            CONNECT BY LEVEL <= 52
                            ) lst
                            LEFT OUTER JOIN
                            (
                            SELECT
                            to_char(Note_created_on - 7/24,'ww/yyyy') as wk,
                            COUNT(*) as amt
                            FROM Notes
                            GROUP BY to_char(Note_created_on - 7/24,'ww/yyyy')
                            ) dat
                            ON lst.wk = dat.wk
                            ORDER BY lst.wk


                            For weeks where there are no note, the left join records a null against that week, so we coalesce it to make it 0.



                            You can, of course, do the query in other ways (many ways), here's a compare:



                            SELECT lst.wk as week, COUNT(dat.wk) as amount FROM
                            (
                            SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
                            FROM dual
                            CONNECT BY LEVEL <= 52
                            ) lst
                            LEFT OUTER JOIN
                            (
                            SELECT
                            to_char(Note_created_on - 7/24,'ww/yyyy') as wk
                            FROM Notes
                            ) dat
                            ON lst.wk = dat.wk
                            GROUP BY lst.wk
                            ORDER BY lst.wk


                            In this form we do the groupby/count after the join. By counting the dat.wk, which for some lst.wk might be NULL, we can omit the coalesce, because count(null) is 0






                            share|improve this answer















                            As mentioned by jarlh:



                            Create a list of weeks:



                            SELECT TO_CHAR(LEVEL, 'FM00')||'/2018' wk
                            FROM dual
                            CONNECT BY LEVEL <= 53


                            This query generates 53 rows, and level is just a number.. 1.. 2.. upto 53. We format it to become 01/2018, 02/2018.. 53/2018



                            If you plan to use this query in other years, you'd be better off making the year dynamic:



                            SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
                            FROM dual
                            CONNECT BY LEVEL <= 53


                            (Credits to Barbaros for pointing out that the last day of any year is reported by Oracle as being in week 53, or said another way 7*52 = 364)



                            We left join the notes data onto it. I wasn't really clear on why you subtracted 7 hours from the date (time zone?) but I left it. I removed the complexity of the count, as you seem to only want the count of records in a particular week. I also removed the double to_char, because you can do it all in a single operation. One doesn't need to TO_CHAR(date, 'WW')||'/'||TO_CHAR(date,'YYYY') etc.. you just tochar with WW/YYYY as a format. Our query now looks like:



                            SELECT lst.wk as week, COALESCE(amt, 0) as amount FROM
                            (
                            SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
                            FROM dual
                            CONNECT BY LEVEL <= 52
                            ) lst
                            LEFT OUTER JOIN
                            (
                            SELECT
                            to_char(Note_created_on - 7/24,'ww/yyyy') as wk,
                            COUNT(*) as amt
                            FROM Notes
                            GROUP BY to_char(Note_created_on - 7/24,'ww/yyyy')
                            ) dat
                            ON lst.wk = dat.wk
                            ORDER BY lst.wk


                            For weeks where there are no note, the left join records a null against that week, so we coalesce it to make it 0.



                            You can, of course, do the query in other ways (many ways), here's a compare:



                            SELECT lst.wk as week, COUNT(dat.wk) as amount FROM
                            (
                            SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
                            FROM dual
                            CONNECT BY LEVEL <= 52
                            ) lst
                            LEFT OUTER JOIN
                            (
                            SELECT
                            to_char(Note_created_on - 7/24,'ww/yyyy') as wk
                            FROM Notes
                            ) dat
                            ON lst.wk = dat.wk
                            GROUP BY lst.wk
                            ORDER BY lst.wk


                            In this form we do the groupby/count after the join. By counting the dat.wk, which for some lst.wk might be NULL, we can omit the coalesce, because count(null) is 0







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Nov 14 '18 at 10:52

























                            answered Nov 14 '18 at 10:22









                            Caius JardCaius Jard

                            12.1k21240




                            12.1k21240



























                                draft saved

                                draft discarded
















































                                Thanks for contributing an answer to Stack Overflow!


                                • 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%2fstackoverflow.com%2fquestions%2f53297631%2fhow-to-fill-value-as-zero-when-no-data-exists-for-particular-week-in-oracle%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

                                Use pre created SQLite database for Android project in kotlin

                                Darth Vader #20

                                Ondo