Active records daily count array w.r.t created_at or updated_at











up vote
1
down vote

favorite












I am working on a school project where I have tables class_standard and enrollments



enrollments belongs_to class_standard and class_standard has many enrollments.



enrollments are created_at in different days. I want to get daily counts of enrollments in last 30 days in an array.



i.e. [# of enrollments 1st day, 2nd day, 3rd day, .....]










share|improve this question


























    up vote
    1
    down vote

    favorite












    I am working on a school project where I have tables class_standard and enrollments



    enrollments belongs_to class_standard and class_standard has many enrollments.



    enrollments are created_at in different days. I want to get daily counts of enrollments in last 30 days in an array.



    i.e. [# of enrollments 1st day, 2nd day, 3rd day, .....]










    share|improve this question
























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      I am working on a school project where I have tables class_standard and enrollments



      enrollments belongs_to class_standard and class_standard has many enrollments.



      enrollments are created_at in different days. I want to get daily counts of enrollments in last 30 days in an array.



      i.e. [# of enrollments 1st day, 2nd day, 3rd day, .....]










      share|improve this question













      I am working on a school project where I have tables class_standard and enrollments



      enrollments belongs_to class_standard and class_standard has many enrollments.



      enrollments are created_at in different days. I want to get daily counts of enrollments in last 30 days in an array.



      i.e. [# of enrollments 1st day, 2nd day, 3rd day, .....]







      ruby-on-rails activerecord rails-activerecord






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked yesterday









      Uzair Nadeem

      2081417




      2081417
























          3 Answers
          3






          active

          oldest

          votes

















          up vote
          0
          down vote













          This is the sample of the code that gets the daily count of Enrollments created and stores them in an array.



          arr =  #initialize an array
          (0..29).each do |x| #run a loop for 30 days
          date = Time.now - x.days #get a specific day
          arr << Enrollment.where(created_at: date.midnight..date.end_of_day).count #get count of enrollments on a specific day and add this to your array
          end
          arr = arr.reverse #reverse the array, because you want the today's count as last item of the array





          share|improve this answer





















          • Thats very inefficient as it will create n number of count queries.
            – max
            yesterday


















          up vote
          0
          down vote













          What you want to do is select a count grouped by day. How exactly to achieve this depends on what database is used.



          Postgres:



          date_trunc('day', created_at)


          MySQL:



          date_format(created_at, '%Y-%m-%d')


          For other db's check the documentation for date functions.



          Altogether the query you want is something like this:



          SELECT 
          count(*) AS count,
          date_trunc('day', created_at) AS day
          FROM "enrollments"
          WHERE (created_at >= ?) -- one month ago
          GROUP BY day
          ORDER BY day


          We can write this in ActiveRecord as:



          Enrollment.select("count(*) AS count, to_char(created_at, 'YYYY-MM-DD') AS day")
          .group("day")
          .order("day")
          .where(created_at: (1.month.ago..Time.current))


          But this gives an ActiveRecord::Relation of records which is not very useful. To get the raw query values we want to use #select_all.



          sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
          .group("day")
          .order("day")
          .where("created_at >= ?", 1.month.ago)
          .to_sql

          results = Enrollment.connection.select_all(sql)


          When you convert the results to an array you will get an array of hashes:



          [{"count"=>10, "day"=>"2018-10-20 00:00:00"}, {"count"=>10, "day"=>"2018-10-21 00:00:00"}, {"count"=>10, "day"=>"2018-10-22 00:00:00"}, {"count"=>10, "day"=>"2018-10-23 00:00:00"}, {"count"=>10, "day"=>"2018-10-24 00:00:00"}, {"count"=>10, "day"=>"2018-10-25 00:00:00"}, ...]


          You can extract the count by mapping the array:



          results.map {|r| r["count"] }


          If you want the results just for one (or more) ClassStandards just add an additional condition to the where clause:



          sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
          .group("day")
          .order("day")
          .where("created_at >= ?", 1.month.ago)
          .where(class_standard: @class_standard)
          .to_sql


          Or you call it off the association:



          sql = @class_standard.enrollments
          .select("count(*) AS count, date_trunc('day', created_at) AS day")
          .group("day")
          .order("day")
          .where("created_at >= ?", 1.month.ago)
          .to_sql





          share|improve this answer























          • date_trunc('day', created_at) and date_format(created_at, '%Y-%m-%d') will return different results by the grouping will be the same.
            – max
            yesterday


















          up vote
          0
          down vote













          If you want to get count of all days including the days where there isn't any enrollment:



          daily_enrollments = 
          i = 29
          while i >= 0
          daily_enrollments >> Enrollments.where( created_at: Time.zone
          .now
          .beginning_of_day-i.day..
          Time.zone
          .now
          .end_of_day-i.day).count

          i = i-1
          end


          Output Example



          [0,0,0,5,4,0,0,0,5,0,23,0,0,23,0,0,1,0,11,0,21,32,44,0,0,9,6,3,22,1]


          This will give you an array of all 30 days. But this isn't seems an efficient code. This will run 30 queries for each record.



          What seems better to me is group the records on created_at and get records for the days which have some records. i.e. excluding days with no record.



          Enrollments.where(created_at: Time.current - 30.days..Time.current)
          .group("date(created_at)")
          .count
          .sort
          .to_h


          Output Example



          {Mon, 19 Nov 2018=>12}





          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',
            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%2f53372313%2factive-records-daily-count-array-w-r-t-created-at-or-updated-at%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








            up vote
            0
            down vote













            This is the sample of the code that gets the daily count of Enrollments created and stores them in an array.



            arr =  #initialize an array
            (0..29).each do |x| #run a loop for 30 days
            date = Time.now - x.days #get a specific day
            arr << Enrollment.where(created_at: date.midnight..date.end_of_day).count #get count of enrollments on a specific day and add this to your array
            end
            arr = arr.reverse #reverse the array, because you want the today's count as last item of the array





            share|improve this answer





















            • Thats very inefficient as it will create n number of count queries.
              – max
              yesterday















            up vote
            0
            down vote













            This is the sample of the code that gets the daily count of Enrollments created and stores them in an array.



            arr =  #initialize an array
            (0..29).each do |x| #run a loop for 30 days
            date = Time.now - x.days #get a specific day
            arr << Enrollment.where(created_at: date.midnight..date.end_of_day).count #get count of enrollments on a specific day and add this to your array
            end
            arr = arr.reverse #reverse the array, because you want the today's count as last item of the array





            share|improve this answer





















            • Thats very inefficient as it will create n number of count queries.
              – max
              yesterday













            up vote
            0
            down vote










            up vote
            0
            down vote









            This is the sample of the code that gets the daily count of Enrollments created and stores them in an array.



            arr =  #initialize an array
            (0..29).each do |x| #run a loop for 30 days
            date = Time.now - x.days #get a specific day
            arr << Enrollment.where(created_at: date.midnight..date.end_of_day).count #get count of enrollments on a specific day and add this to your array
            end
            arr = arr.reverse #reverse the array, because you want the today's count as last item of the array





            share|improve this answer












            This is the sample of the code that gets the daily count of Enrollments created and stores them in an array.



            arr =  #initialize an array
            (0..29).each do |x| #run a loop for 30 days
            date = Time.now - x.days #get a specific day
            arr << Enrollment.where(created_at: date.midnight..date.end_of_day).count #get count of enrollments on a specific day and add this to your array
            end
            arr = arr.reverse #reverse the array, because you want the today's count as last item of the array






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered yesterday









            Saqib Shahzad

            534119




            534119












            • Thats very inefficient as it will create n number of count queries.
              – max
              yesterday


















            • Thats very inefficient as it will create n number of count queries.
              – max
              yesterday
















            Thats very inefficient as it will create n number of count queries.
            – max
            yesterday




            Thats very inefficient as it will create n number of count queries.
            – max
            yesterday












            up vote
            0
            down vote













            What you want to do is select a count grouped by day. How exactly to achieve this depends on what database is used.



            Postgres:



            date_trunc('day', created_at)


            MySQL:



            date_format(created_at, '%Y-%m-%d')


            For other db's check the documentation for date functions.



            Altogether the query you want is something like this:



            SELECT 
            count(*) AS count,
            date_trunc('day', created_at) AS day
            FROM "enrollments"
            WHERE (created_at >= ?) -- one month ago
            GROUP BY day
            ORDER BY day


            We can write this in ActiveRecord as:



            Enrollment.select("count(*) AS count, to_char(created_at, 'YYYY-MM-DD') AS day")
            .group("day")
            .order("day")
            .where(created_at: (1.month.ago..Time.current))


            But this gives an ActiveRecord::Relation of records which is not very useful. To get the raw query values we want to use #select_all.



            sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
            .group("day")
            .order("day")
            .where("created_at >= ?", 1.month.ago)
            .to_sql

            results = Enrollment.connection.select_all(sql)


            When you convert the results to an array you will get an array of hashes:



            [{"count"=>10, "day"=>"2018-10-20 00:00:00"}, {"count"=>10, "day"=>"2018-10-21 00:00:00"}, {"count"=>10, "day"=>"2018-10-22 00:00:00"}, {"count"=>10, "day"=>"2018-10-23 00:00:00"}, {"count"=>10, "day"=>"2018-10-24 00:00:00"}, {"count"=>10, "day"=>"2018-10-25 00:00:00"}, ...]


            You can extract the count by mapping the array:



            results.map {|r| r["count"] }


            If you want the results just for one (or more) ClassStandards just add an additional condition to the where clause:



            sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
            .group("day")
            .order("day")
            .where("created_at >= ?", 1.month.ago)
            .where(class_standard: @class_standard)
            .to_sql


            Or you call it off the association:



            sql = @class_standard.enrollments
            .select("count(*) AS count, date_trunc('day', created_at) AS day")
            .group("day")
            .order("day")
            .where("created_at >= ?", 1.month.ago)
            .to_sql





            share|improve this answer























            • date_trunc('day', created_at) and date_format(created_at, '%Y-%m-%d') will return different results by the grouping will be the same.
              – max
              yesterday















            up vote
            0
            down vote













            What you want to do is select a count grouped by day. How exactly to achieve this depends on what database is used.



            Postgres:



            date_trunc('day', created_at)


            MySQL:



            date_format(created_at, '%Y-%m-%d')


            For other db's check the documentation for date functions.



            Altogether the query you want is something like this:



            SELECT 
            count(*) AS count,
            date_trunc('day', created_at) AS day
            FROM "enrollments"
            WHERE (created_at >= ?) -- one month ago
            GROUP BY day
            ORDER BY day


            We can write this in ActiveRecord as:



            Enrollment.select("count(*) AS count, to_char(created_at, 'YYYY-MM-DD') AS day")
            .group("day")
            .order("day")
            .where(created_at: (1.month.ago..Time.current))


            But this gives an ActiveRecord::Relation of records which is not very useful. To get the raw query values we want to use #select_all.



            sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
            .group("day")
            .order("day")
            .where("created_at >= ?", 1.month.ago)
            .to_sql

            results = Enrollment.connection.select_all(sql)


            When you convert the results to an array you will get an array of hashes:



            [{"count"=>10, "day"=>"2018-10-20 00:00:00"}, {"count"=>10, "day"=>"2018-10-21 00:00:00"}, {"count"=>10, "day"=>"2018-10-22 00:00:00"}, {"count"=>10, "day"=>"2018-10-23 00:00:00"}, {"count"=>10, "day"=>"2018-10-24 00:00:00"}, {"count"=>10, "day"=>"2018-10-25 00:00:00"}, ...]


            You can extract the count by mapping the array:



            results.map {|r| r["count"] }


            If you want the results just for one (or more) ClassStandards just add an additional condition to the where clause:



            sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
            .group("day")
            .order("day")
            .where("created_at >= ?", 1.month.ago)
            .where(class_standard: @class_standard)
            .to_sql


            Or you call it off the association:



            sql = @class_standard.enrollments
            .select("count(*) AS count, date_trunc('day', created_at) AS day")
            .group("day")
            .order("day")
            .where("created_at >= ?", 1.month.ago)
            .to_sql





            share|improve this answer























            • date_trunc('day', created_at) and date_format(created_at, '%Y-%m-%d') will return different results by the grouping will be the same.
              – max
              yesterday













            up vote
            0
            down vote










            up vote
            0
            down vote









            What you want to do is select a count grouped by day. How exactly to achieve this depends on what database is used.



            Postgres:



            date_trunc('day', created_at)


            MySQL:



            date_format(created_at, '%Y-%m-%d')


            For other db's check the documentation for date functions.



            Altogether the query you want is something like this:



            SELECT 
            count(*) AS count,
            date_trunc('day', created_at) AS day
            FROM "enrollments"
            WHERE (created_at >= ?) -- one month ago
            GROUP BY day
            ORDER BY day


            We can write this in ActiveRecord as:



            Enrollment.select("count(*) AS count, to_char(created_at, 'YYYY-MM-DD') AS day")
            .group("day")
            .order("day")
            .where(created_at: (1.month.ago..Time.current))


            But this gives an ActiveRecord::Relation of records which is not very useful. To get the raw query values we want to use #select_all.



            sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
            .group("day")
            .order("day")
            .where("created_at >= ?", 1.month.ago)
            .to_sql

            results = Enrollment.connection.select_all(sql)


            When you convert the results to an array you will get an array of hashes:



            [{"count"=>10, "day"=>"2018-10-20 00:00:00"}, {"count"=>10, "day"=>"2018-10-21 00:00:00"}, {"count"=>10, "day"=>"2018-10-22 00:00:00"}, {"count"=>10, "day"=>"2018-10-23 00:00:00"}, {"count"=>10, "day"=>"2018-10-24 00:00:00"}, {"count"=>10, "day"=>"2018-10-25 00:00:00"}, ...]


            You can extract the count by mapping the array:



            results.map {|r| r["count"] }


            If you want the results just for one (or more) ClassStandards just add an additional condition to the where clause:



            sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
            .group("day")
            .order("day")
            .where("created_at >= ?", 1.month.ago)
            .where(class_standard: @class_standard)
            .to_sql


            Or you call it off the association:



            sql = @class_standard.enrollments
            .select("count(*) AS count, date_trunc('day', created_at) AS day")
            .group("day")
            .order("day")
            .where("created_at >= ?", 1.month.ago)
            .to_sql





            share|improve this answer














            What you want to do is select a count grouped by day. How exactly to achieve this depends on what database is used.



            Postgres:



            date_trunc('day', created_at)


            MySQL:



            date_format(created_at, '%Y-%m-%d')


            For other db's check the documentation for date functions.



            Altogether the query you want is something like this:



            SELECT 
            count(*) AS count,
            date_trunc('day', created_at) AS day
            FROM "enrollments"
            WHERE (created_at >= ?) -- one month ago
            GROUP BY day
            ORDER BY day


            We can write this in ActiveRecord as:



            Enrollment.select("count(*) AS count, to_char(created_at, 'YYYY-MM-DD') AS day")
            .group("day")
            .order("day")
            .where(created_at: (1.month.ago..Time.current))


            But this gives an ActiveRecord::Relation of records which is not very useful. To get the raw query values we want to use #select_all.



            sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
            .group("day")
            .order("day")
            .where("created_at >= ?", 1.month.ago)
            .to_sql

            results = Enrollment.connection.select_all(sql)


            When you convert the results to an array you will get an array of hashes:



            [{"count"=>10, "day"=>"2018-10-20 00:00:00"}, {"count"=>10, "day"=>"2018-10-21 00:00:00"}, {"count"=>10, "day"=>"2018-10-22 00:00:00"}, {"count"=>10, "day"=>"2018-10-23 00:00:00"}, {"count"=>10, "day"=>"2018-10-24 00:00:00"}, {"count"=>10, "day"=>"2018-10-25 00:00:00"}, ...]


            You can extract the count by mapping the array:



            results.map {|r| r["count"] }


            If you want the results just for one (or more) ClassStandards just add an additional condition to the where clause:



            sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
            .group("day")
            .order("day")
            .where("created_at >= ?", 1.month.ago)
            .where(class_standard: @class_standard)
            .to_sql


            Or you call it off the association:



            sql = @class_standard.enrollments
            .select("count(*) AS count, date_trunc('day', created_at) AS day")
            .group("day")
            .order("day")
            .where("created_at >= ?", 1.month.ago)
            .to_sql






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited yesterday

























            answered yesterday









            max

            43.8k856103




            43.8k856103












            • date_trunc('day', created_at) and date_format(created_at, '%Y-%m-%d') will return different results by the grouping will be the same.
              – max
              yesterday


















            • date_trunc('day', created_at) and date_format(created_at, '%Y-%m-%d') will return different results by the grouping will be the same.
              – max
              yesterday
















            date_trunc('day', created_at) and date_format(created_at, '%Y-%m-%d') will return different results by the grouping will be the same.
            – max
            yesterday




            date_trunc('day', created_at) and date_format(created_at, '%Y-%m-%d') will return different results by the grouping will be the same.
            – max
            yesterday










            up vote
            0
            down vote













            If you want to get count of all days including the days where there isn't any enrollment:



            daily_enrollments = 
            i = 29
            while i >= 0
            daily_enrollments >> Enrollments.where( created_at: Time.zone
            .now
            .beginning_of_day-i.day..
            Time.zone
            .now
            .end_of_day-i.day).count

            i = i-1
            end


            Output Example



            [0,0,0,5,4,0,0,0,5,0,23,0,0,23,0,0,1,0,11,0,21,32,44,0,0,9,6,3,22,1]


            This will give you an array of all 30 days. But this isn't seems an efficient code. This will run 30 queries for each record.



            What seems better to me is group the records on created_at and get records for the days which have some records. i.e. excluding days with no record.



            Enrollments.where(created_at: Time.current - 30.days..Time.current)
            .group("date(created_at)")
            .count
            .sort
            .to_h


            Output Example



            {Mon, 19 Nov 2018=>12}





            share|improve this answer

























              up vote
              0
              down vote













              If you want to get count of all days including the days where there isn't any enrollment:



              daily_enrollments = 
              i = 29
              while i >= 0
              daily_enrollments >> Enrollments.where( created_at: Time.zone
              .now
              .beginning_of_day-i.day..
              Time.zone
              .now
              .end_of_day-i.day).count

              i = i-1
              end


              Output Example



              [0,0,0,5,4,0,0,0,5,0,23,0,0,23,0,0,1,0,11,0,21,32,44,0,0,9,6,3,22,1]


              This will give you an array of all 30 days. But this isn't seems an efficient code. This will run 30 queries for each record.



              What seems better to me is group the records on created_at and get records for the days which have some records. i.e. excluding days with no record.



              Enrollments.where(created_at: Time.current - 30.days..Time.current)
              .group("date(created_at)")
              .count
              .sort
              .to_h


              Output Example



              {Mon, 19 Nov 2018=>12}





              share|improve this answer























                up vote
                0
                down vote










                up vote
                0
                down vote









                If you want to get count of all days including the days where there isn't any enrollment:



                daily_enrollments = 
                i = 29
                while i >= 0
                daily_enrollments >> Enrollments.where( created_at: Time.zone
                .now
                .beginning_of_day-i.day..
                Time.zone
                .now
                .end_of_day-i.day).count

                i = i-1
                end


                Output Example



                [0,0,0,5,4,0,0,0,5,0,23,0,0,23,0,0,1,0,11,0,21,32,44,0,0,9,6,3,22,1]


                This will give you an array of all 30 days. But this isn't seems an efficient code. This will run 30 queries for each record.



                What seems better to me is group the records on created_at and get records for the days which have some records. i.e. excluding days with no record.



                Enrollments.where(created_at: Time.current - 30.days..Time.current)
                .group("date(created_at)")
                .count
                .sort
                .to_h


                Output Example



                {Mon, 19 Nov 2018=>12}





                share|improve this answer












                If you want to get count of all days including the days where there isn't any enrollment:



                daily_enrollments = 
                i = 29
                while i >= 0
                daily_enrollments >> Enrollments.where( created_at: Time.zone
                .now
                .beginning_of_day-i.day..
                Time.zone
                .now
                .end_of_day-i.day).count

                i = i-1
                end


                Output Example



                [0,0,0,5,4,0,0,0,5,0,23,0,0,23,0,0,1,0,11,0,21,32,44,0,0,9,6,3,22,1]


                This will give you an array of all 30 days. But this isn't seems an efficient code. This will run 30 queries for each record.



                What seems better to me is group the records on created_at and get records for the days which have some records. i.e. excluding days with no record.



                Enrollments.where(created_at: Time.current - 30.days..Time.current)
                .group("date(created_at)")
                .count
                .sort
                .to_h


                Output Example



                {Mon, 19 Nov 2018=>12}






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered yesterday









                Uzair Nadeem

                2081417




                2081417






























                     

                    draft saved


                    draft discarded



















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53372313%2factive-records-daily-count-array-w-r-t-created-at-or-updated-at%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

                    Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

                    Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

                    A Topological Invariant for $pi_3(U(n))$