selecting records without value










0















I have a problem when I'm trying to reach the desired result. The task looks simple — make a daily count of occurrences of the event for top countries.



The main table looks like this:



id | date | country | col1 | col2 | ...
1 | 2018-01-01 21:21:21 | US | value 1 | value 2 | ...
2 | 2018-01-01 22:32:54 | UK | value 1 | value 2 | ...


From this table, I want to get daily event counts by the country, which is achieved by



SELECT date::DATE AT TIME ZONE 'UTC', country, COALESCE(count(id),0) FROM tab1
GROUP BY 1, 2


The problem comes when there is no event was made by an UK user on 2 January 2018



country_events
date | country | count
2018-01-01 | US | 23
2018-01-01 | UK | 5
2018-01-02 | US | 30
2018-01-02 | UK | 0 -> is desired result, but row is missing


I've tried to generate date series and series of countries which I'm looking for, then CROSS JOIN these two tables. This helper with columns date and country I've left joined with my result table like



SELECT * FROM helper h
LEFT JOIN country_events c ON c.date::DATE = h.date::DATE AND c.country = h.country


I'm using PostgreSQL.










share|improve this question




























    0















    I have a problem when I'm trying to reach the desired result. The task looks simple — make a daily count of occurrences of the event for top countries.



    The main table looks like this:



    id | date | country | col1 | col2 | ...
    1 | 2018-01-01 21:21:21 | US | value 1 | value 2 | ...
    2 | 2018-01-01 22:32:54 | UK | value 1 | value 2 | ...


    From this table, I want to get daily event counts by the country, which is achieved by



    SELECT date::DATE AT TIME ZONE 'UTC', country, COALESCE(count(id),0) FROM tab1
    GROUP BY 1, 2


    The problem comes when there is no event was made by an UK user on 2 January 2018



    country_events
    date | country | count
    2018-01-01 | US | 23
    2018-01-01 | UK | 5
    2018-01-02 | US | 30
    2018-01-02 | UK | 0 -> is desired result, but row is missing


    I've tried to generate date series and series of countries which I'm looking for, then CROSS JOIN these two tables. This helper with columns date and country I've left joined with my result table like



    SELECT * FROM helper h
    LEFT JOIN country_events c ON c.date::DATE = h.date::DATE AND c.country = h.country


    I'm using PostgreSQL.










    share|improve this question


























      0












      0








      0








      I have a problem when I'm trying to reach the desired result. The task looks simple — make a daily count of occurrences of the event for top countries.



      The main table looks like this:



      id | date | country | col1 | col2 | ...
      1 | 2018-01-01 21:21:21 | US | value 1 | value 2 | ...
      2 | 2018-01-01 22:32:54 | UK | value 1 | value 2 | ...


      From this table, I want to get daily event counts by the country, which is achieved by



      SELECT date::DATE AT TIME ZONE 'UTC', country, COALESCE(count(id),0) FROM tab1
      GROUP BY 1, 2


      The problem comes when there is no event was made by an UK user on 2 January 2018



      country_events
      date | country | count
      2018-01-01 | US | 23
      2018-01-01 | UK | 5
      2018-01-02 | US | 30
      2018-01-02 | UK | 0 -> is desired result, but row is missing


      I've tried to generate date series and series of countries which I'm looking for, then CROSS JOIN these two tables. This helper with columns date and country I've left joined with my result table like



      SELECT * FROM helper h
      LEFT JOIN country_events c ON c.date::DATE = h.date::DATE AND c.country = h.country


      I'm using PostgreSQL.










      share|improve this question
















      I have a problem when I'm trying to reach the desired result. The task looks simple — make a daily count of occurrences of the event for top countries.



      The main table looks like this:



      id | date | country | col1 | col2 | ...
      1 | 2018-01-01 21:21:21 | US | value 1 | value 2 | ...
      2 | 2018-01-01 22:32:54 | UK | value 1 | value 2 | ...


      From this table, I want to get daily event counts by the country, which is achieved by



      SELECT date::DATE AT TIME ZONE 'UTC', country, COALESCE(count(id),0) FROM tab1
      GROUP BY 1, 2


      The problem comes when there is no event was made by an UK user on 2 January 2018



      country_events
      date | country | count
      2018-01-01 | US | 23
      2018-01-01 | UK | 5
      2018-01-02 | US | 30
      2018-01-02 | UK | 0 -> is desired result, but row is missing


      I've tried to generate date series and series of countries which I'm looking for, then CROSS JOIN these two tables. This helper with columns date and country I've left joined with my result table like



      SELECT * FROM helper h
      LEFT JOIN country_events c ON c.date::DATE = h.date::DATE AND c.country = h.country


      I'm using PostgreSQL.







      postgresql join






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 15 '18 at 18:27









      Laurenz Albe

      51.1k103050




      51.1k103050










      asked Nov 15 '18 at 18:09









      skutikskutik

      5217




      5217






















          1 Answer
          1






          active

          oldest

          votes


















          0














          You need an outer join, not a cross join:



          SELECT tab1.date::date, tab1.country, coalesce(count(*), 0)
          FROM generate_series(TIMESTAMP '2018-01-01 00:00:00',
          TIMESTAMP '2018-01-31 00:00:00',
          INTERVAL '1 day') AS ts(d)
          LEFT JOIN tab1 ON tab1.date >= ts.d AND tab1.date < ts.d + INTERVAL '1 day'
          GROUP BY tab1.date::date, tab1.country
          ORDER BY tab1.date::date, tab1.country;


          This will give the desired list for January 2018.






          share|improve this answer























          • It's not working. Perhaps because when I make select from the tab1, there is no record date for this date, so row is not created like date | country | count 2018-01-01 | UK | 5 2018-01-03 | UK | 7 in this case, there is no way how to join tab1 select when there is no combination of 2018-01-01 with UK value... Isn't it?

            – skutik
            Nov 16 '18 at 7:41











          • Can you specify "it is not working"? Are there errors? Results different from what you described in your question? It might help if you add the CREATE TABLE statement for tab1 to the question.

            – Laurenz Albe
            Nov 16 '18 at 9:35











          • I'm sorry. There is no error but also no progress. Little progress was when I've changed tab1.date for ts.d but it can be caused by using ON tab1.date = ts.d. With this change, I've got the result like this 2018-01-02 | NULL | 0 -> the UK country is missing. Is any approach how to achieve 2018-01-02 | UK | 0 without making SELECT for each country with CASE WHEN country IS NULL THEN 'UK' ELSE country END and then union them all?

            – skutik
            Nov 16 '18 at 11:34












          • I don't understand. How was your CREATE TABLE statement?

            – Laurenz Albe
            Nov 16 '18 at 11:51










          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%2f53325507%2fselecting-records-without-value%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          0














          You need an outer join, not a cross join:



          SELECT tab1.date::date, tab1.country, coalesce(count(*), 0)
          FROM generate_series(TIMESTAMP '2018-01-01 00:00:00',
          TIMESTAMP '2018-01-31 00:00:00',
          INTERVAL '1 day') AS ts(d)
          LEFT JOIN tab1 ON tab1.date >= ts.d AND tab1.date < ts.d + INTERVAL '1 day'
          GROUP BY tab1.date::date, tab1.country
          ORDER BY tab1.date::date, tab1.country;


          This will give the desired list for January 2018.






          share|improve this answer























          • It's not working. Perhaps because when I make select from the tab1, there is no record date for this date, so row is not created like date | country | count 2018-01-01 | UK | 5 2018-01-03 | UK | 7 in this case, there is no way how to join tab1 select when there is no combination of 2018-01-01 with UK value... Isn't it?

            – skutik
            Nov 16 '18 at 7:41











          • Can you specify "it is not working"? Are there errors? Results different from what you described in your question? It might help if you add the CREATE TABLE statement for tab1 to the question.

            – Laurenz Albe
            Nov 16 '18 at 9:35











          • I'm sorry. There is no error but also no progress. Little progress was when I've changed tab1.date for ts.d but it can be caused by using ON tab1.date = ts.d. With this change, I've got the result like this 2018-01-02 | NULL | 0 -> the UK country is missing. Is any approach how to achieve 2018-01-02 | UK | 0 without making SELECT for each country with CASE WHEN country IS NULL THEN 'UK' ELSE country END and then union them all?

            – skutik
            Nov 16 '18 at 11:34












          • I don't understand. How was your CREATE TABLE statement?

            – Laurenz Albe
            Nov 16 '18 at 11:51















          0














          You need an outer join, not a cross join:



          SELECT tab1.date::date, tab1.country, coalesce(count(*), 0)
          FROM generate_series(TIMESTAMP '2018-01-01 00:00:00',
          TIMESTAMP '2018-01-31 00:00:00',
          INTERVAL '1 day') AS ts(d)
          LEFT JOIN tab1 ON tab1.date >= ts.d AND tab1.date < ts.d + INTERVAL '1 day'
          GROUP BY tab1.date::date, tab1.country
          ORDER BY tab1.date::date, tab1.country;


          This will give the desired list for January 2018.






          share|improve this answer























          • It's not working. Perhaps because when I make select from the tab1, there is no record date for this date, so row is not created like date | country | count 2018-01-01 | UK | 5 2018-01-03 | UK | 7 in this case, there is no way how to join tab1 select when there is no combination of 2018-01-01 with UK value... Isn't it?

            – skutik
            Nov 16 '18 at 7:41











          • Can you specify "it is not working"? Are there errors? Results different from what you described in your question? It might help if you add the CREATE TABLE statement for tab1 to the question.

            – Laurenz Albe
            Nov 16 '18 at 9:35











          • I'm sorry. There is no error but also no progress. Little progress was when I've changed tab1.date for ts.d but it can be caused by using ON tab1.date = ts.d. With this change, I've got the result like this 2018-01-02 | NULL | 0 -> the UK country is missing. Is any approach how to achieve 2018-01-02 | UK | 0 without making SELECT for each country with CASE WHEN country IS NULL THEN 'UK' ELSE country END and then union them all?

            – skutik
            Nov 16 '18 at 11:34












          • I don't understand. How was your CREATE TABLE statement?

            – Laurenz Albe
            Nov 16 '18 at 11:51













          0












          0








          0







          You need an outer join, not a cross join:



          SELECT tab1.date::date, tab1.country, coalesce(count(*), 0)
          FROM generate_series(TIMESTAMP '2018-01-01 00:00:00',
          TIMESTAMP '2018-01-31 00:00:00',
          INTERVAL '1 day') AS ts(d)
          LEFT JOIN tab1 ON tab1.date >= ts.d AND tab1.date < ts.d + INTERVAL '1 day'
          GROUP BY tab1.date::date, tab1.country
          ORDER BY tab1.date::date, tab1.country;


          This will give the desired list for January 2018.






          share|improve this answer













          You need an outer join, not a cross join:



          SELECT tab1.date::date, tab1.country, coalesce(count(*), 0)
          FROM generate_series(TIMESTAMP '2018-01-01 00:00:00',
          TIMESTAMP '2018-01-31 00:00:00',
          INTERVAL '1 day') AS ts(d)
          LEFT JOIN tab1 ON tab1.date >= ts.d AND tab1.date < ts.d + INTERVAL '1 day'
          GROUP BY tab1.date::date, tab1.country
          ORDER BY tab1.date::date, tab1.country;


          This will give the desired list for January 2018.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 15 '18 at 18:24









          Laurenz AlbeLaurenz Albe

          51.1k103050




          51.1k103050












          • It's not working. Perhaps because when I make select from the tab1, there is no record date for this date, so row is not created like date | country | count 2018-01-01 | UK | 5 2018-01-03 | UK | 7 in this case, there is no way how to join tab1 select when there is no combination of 2018-01-01 with UK value... Isn't it?

            – skutik
            Nov 16 '18 at 7:41











          • Can you specify "it is not working"? Are there errors? Results different from what you described in your question? It might help if you add the CREATE TABLE statement for tab1 to the question.

            – Laurenz Albe
            Nov 16 '18 at 9:35











          • I'm sorry. There is no error but also no progress. Little progress was when I've changed tab1.date for ts.d but it can be caused by using ON tab1.date = ts.d. With this change, I've got the result like this 2018-01-02 | NULL | 0 -> the UK country is missing. Is any approach how to achieve 2018-01-02 | UK | 0 without making SELECT for each country with CASE WHEN country IS NULL THEN 'UK' ELSE country END and then union them all?

            – skutik
            Nov 16 '18 at 11:34












          • I don't understand. How was your CREATE TABLE statement?

            – Laurenz Albe
            Nov 16 '18 at 11:51

















          • It's not working. Perhaps because when I make select from the tab1, there is no record date for this date, so row is not created like date | country | count 2018-01-01 | UK | 5 2018-01-03 | UK | 7 in this case, there is no way how to join tab1 select when there is no combination of 2018-01-01 with UK value... Isn't it?

            – skutik
            Nov 16 '18 at 7:41











          • Can you specify "it is not working"? Are there errors? Results different from what you described in your question? It might help if you add the CREATE TABLE statement for tab1 to the question.

            – Laurenz Albe
            Nov 16 '18 at 9:35











          • I'm sorry. There is no error but also no progress. Little progress was when I've changed tab1.date for ts.d but it can be caused by using ON tab1.date = ts.d. With this change, I've got the result like this 2018-01-02 | NULL | 0 -> the UK country is missing. Is any approach how to achieve 2018-01-02 | UK | 0 without making SELECT for each country with CASE WHEN country IS NULL THEN 'UK' ELSE country END and then union them all?

            – skutik
            Nov 16 '18 at 11:34












          • I don't understand. How was your CREATE TABLE statement?

            – Laurenz Albe
            Nov 16 '18 at 11:51
















          It's not working. Perhaps because when I make select from the tab1, there is no record date for this date, so row is not created like date | country | count 2018-01-01 | UK | 5 2018-01-03 | UK | 7 in this case, there is no way how to join tab1 select when there is no combination of 2018-01-01 with UK value... Isn't it?

          – skutik
          Nov 16 '18 at 7:41





          It's not working. Perhaps because when I make select from the tab1, there is no record date for this date, so row is not created like date | country | count 2018-01-01 | UK | 5 2018-01-03 | UK | 7 in this case, there is no way how to join tab1 select when there is no combination of 2018-01-01 with UK value... Isn't it?

          – skutik
          Nov 16 '18 at 7:41













          Can you specify "it is not working"? Are there errors? Results different from what you described in your question? It might help if you add the CREATE TABLE statement for tab1 to the question.

          – Laurenz Albe
          Nov 16 '18 at 9:35





          Can you specify "it is not working"? Are there errors? Results different from what you described in your question? It might help if you add the CREATE TABLE statement for tab1 to the question.

          – Laurenz Albe
          Nov 16 '18 at 9:35













          I'm sorry. There is no error but also no progress. Little progress was when I've changed tab1.date for ts.d but it can be caused by using ON tab1.date = ts.d. With this change, I've got the result like this 2018-01-02 | NULL | 0 -> the UK country is missing. Is any approach how to achieve 2018-01-02 | UK | 0 without making SELECT for each country with CASE WHEN country IS NULL THEN 'UK' ELSE country END and then union them all?

          – skutik
          Nov 16 '18 at 11:34






          I'm sorry. There is no error but also no progress. Little progress was when I've changed tab1.date for ts.d but it can be caused by using ON tab1.date = ts.d. With this change, I've got the result like this 2018-01-02 | NULL | 0 -> the UK country is missing. Is any approach how to achieve 2018-01-02 | UK | 0 without making SELECT for each country with CASE WHEN country IS NULL THEN 'UK' ELSE country END and then union them all?

          – skutik
          Nov 16 '18 at 11:34














          I don't understand. How was your CREATE TABLE statement?

          – Laurenz Albe
          Nov 16 '18 at 11:51





          I don't understand. How was your CREATE TABLE statement?

          – Laurenz Albe
          Nov 16 '18 at 11:51



















          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%2f53325507%2fselecting-records-without-value%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







          這個網誌中的熱門文章

          How to read a connectionString WITH PROVIDER in .NET Core?

          Node.js Script on GitHub Pages or Amazon S3

          Museum of Modern and Contemporary Art of Trento and Rovereto