Converting SQL to Arel - column […] must appear in the GROUP BY clause












0















I have a working SQL query and I would like to convert it into an Arel, but I seem to keep on running into the same error.



Working SQL:



Order.find_by_sql(
"SELECT COUNT(order_number) AS order_count,
restaurant_id, date_part('month', date) AS date_month,
date_part('year', date) AS date_year
FROM orders
WHERE restaurant_id is not null
GROUP BY(restaurant_id, date_part('month', date), date_part('year', date))
ORDER BY date_part('year', date) desc, date_part('month', date) desc;"
)


Attempt 1 (not working)



orders = Order.arel_table

Order
.where.not(restaurant_id: nil)
.select(:restaurant_id)
.select(:date)
.select(Order.arel_table[:order_number].count.as('order_count'))
.select(
Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), :date]),
Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
)
.group(
:restaurant_id,
Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
)


Attempt 2 (not working)



orders = Order.arel_table
query = orders
.where(orders[:restaurant_id].not_eq(nil))
.project(
orders[:restaurant_id],
Order.arel_table[:order_number].count.as('order_count'),
Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]).as('date_month'),
Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]]).as('date_year'),
)
.group(
orders[:restaurant_id],
Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
)
.order(orders[:date].desc)
.to_sql
Order.find_by_sql(query)


Both approaches result in the following error:




PG::GroupingError: ERROR: column "orders.date" must appear in the GROUP BY clause or be used in an aggregate function




The problem is that I don't want to group by date, but by month. Any tips on how to solve it?



I also originally tried Arel::Nodes::NamedFunction.new('date_part', ['month', :date]) instead of Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]) but it resulted with the following:




Unsupported argument type: String. Construct an Arel node instead.




Any help greatly appreciated. Thanks!










share|improve this question



























    0















    I have a working SQL query and I would like to convert it into an Arel, but I seem to keep on running into the same error.



    Working SQL:



    Order.find_by_sql(
    "SELECT COUNT(order_number) AS order_count,
    restaurant_id, date_part('month', date) AS date_month,
    date_part('year', date) AS date_year
    FROM orders
    WHERE restaurant_id is not null
    GROUP BY(restaurant_id, date_part('month', date), date_part('year', date))
    ORDER BY date_part('year', date) desc, date_part('month', date) desc;"
    )


    Attempt 1 (not working)



    orders = Order.arel_table

    Order
    .where.not(restaurant_id: nil)
    .select(:restaurant_id)
    .select(:date)
    .select(Order.arel_table[:order_number].count.as('order_count'))
    .select(
    Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), :date]),
    Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
    )
    .group(
    :restaurant_id,
    Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
    Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
    )


    Attempt 2 (not working)



    orders = Order.arel_table
    query = orders
    .where(orders[:restaurant_id].not_eq(nil))
    .project(
    orders[:restaurant_id],
    Order.arel_table[:order_number].count.as('order_count'),
    Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]).as('date_month'),
    Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]]).as('date_year'),
    )
    .group(
    orders[:restaurant_id],
    Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
    Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
    )
    .order(orders[:date].desc)
    .to_sql
    Order.find_by_sql(query)


    Both approaches result in the following error:




    PG::GroupingError: ERROR: column "orders.date" must appear in the GROUP BY clause or be used in an aggregate function




    The problem is that I don't want to group by date, but by month. Any tips on how to solve it?



    I also originally tried Arel::Nodes::NamedFunction.new('date_part', ['month', :date]) instead of Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]) but it resulted with the following:




    Unsupported argument type: String. Construct an Arel node instead.




    Any help greatly appreciated. Thanks!










    share|improve this question

























      0












      0








      0








      I have a working SQL query and I would like to convert it into an Arel, but I seem to keep on running into the same error.



      Working SQL:



      Order.find_by_sql(
      "SELECT COUNT(order_number) AS order_count,
      restaurant_id, date_part('month', date) AS date_month,
      date_part('year', date) AS date_year
      FROM orders
      WHERE restaurant_id is not null
      GROUP BY(restaurant_id, date_part('month', date), date_part('year', date))
      ORDER BY date_part('year', date) desc, date_part('month', date) desc;"
      )


      Attempt 1 (not working)



      orders = Order.arel_table

      Order
      .where.not(restaurant_id: nil)
      .select(:restaurant_id)
      .select(:date)
      .select(Order.arel_table[:order_number].count.as('order_count'))
      .select(
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), :date]),
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
      )
      .group(
      :restaurant_id,
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
      )


      Attempt 2 (not working)



      orders = Order.arel_table
      query = orders
      .where(orders[:restaurant_id].not_eq(nil))
      .project(
      orders[:restaurant_id],
      Order.arel_table[:order_number].count.as('order_count'),
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]).as('date_month'),
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]]).as('date_year'),
      )
      .group(
      orders[:restaurant_id],
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
      )
      .order(orders[:date].desc)
      .to_sql
      Order.find_by_sql(query)


      Both approaches result in the following error:




      PG::GroupingError: ERROR: column "orders.date" must appear in the GROUP BY clause or be used in an aggregate function




      The problem is that I don't want to group by date, but by month. Any tips on how to solve it?



      I also originally tried Arel::Nodes::NamedFunction.new('date_part', ['month', :date]) instead of Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]) but it resulted with the following:




      Unsupported argument type: String. Construct an Arel node instead.




      Any help greatly appreciated. Thanks!










      share|improve this question














      I have a working SQL query and I would like to convert it into an Arel, but I seem to keep on running into the same error.



      Working SQL:



      Order.find_by_sql(
      "SELECT COUNT(order_number) AS order_count,
      restaurant_id, date_part('month', date) AS date_month,
      date_part('year', date) AS date_year
      FROM orders
      WHERE restaurant_id is not null
      GROUP BY(restaurant_id, date_part('month', date), date_part('year', date))
      ORDER BY date_part('year', date) desc, date_part('month', date) desc;"
      )


      Attempt 1 (not working)



      orders = Order.arel_table

      Order
      .where.not(restaurant_id: nil)
      .select(:restaurant_id)
      .select(:date)
      .select(Order.arel_table[:order_number].count.as('order_count'))
      .select(
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), :date]),
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
      )
      .group(
      :restaurant_id,
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
      )


      Attempt 2 (not working)



      orders = Order.arel_table
      query = orders
      .where(orders[:restaurant_id].not_eq(nil))
      .project(
      orders[:restaurant_id],
      Order.arel_table[:order_number].count.as('order_count'),
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]).as('date_month'),
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]]).as('date_year'),
      )
      .group(
      orders[:restaurant_id],
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
      Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
      )
      .order(orders[:date].desc)
      .to_sql
      Order.find_by_sql(query)


      Both approaches result in the following error:




      PG::GroupingError: ERROR: column "orders.date" must appear in the GROUP BY clause or be used in an aggregate function




      The problem is that I don't want to group by date, but by month. Any tips on how to solve it?



      I also originally tried Arel::Nodes::NamedFunction.new('date_part', ['month', :date]) instead of Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]) but it resulted with the following:




      Unsupported argument type: String. Construct an Arel node instead.




      Any help greatly appreciated. Thanks!







      postgresql arel






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 26 '18 at 8:48









      Joanna GaudynJoanna Gaudyn

      252113




      252113
























          1 Answer
          1






          active

          oldest

          votes


















          0














          So after hours of digging it turns out the big gotcha! of my problem was a default_scope set on my Order model - that's where sorting by :date was happening. In the end I decided to remove the default scope, use sorting where it was actually needed and what I was left it regarding my query was this:



          orders = Order.arel_table
          query = orders
          .where(orders[:restaurant_id].not_eq(nil))
          .project(
          orders[:restaurant_id],
          Order.arel_table[:order_number].count.as('order_count'),
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]).as('date_month'),
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]]).as('date_year'),
          )
          .group(
          orders[:restaurant_id],
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
          )
          .order(
          orders[:restaurant_id],
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), date]).desc,
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), date]).desc

          )
          .to_sql

          Order.find_by_sql(query)


          Lesson learnt: avoid default_scopes whenever possible. If you work alone, you're likely to forget you used it over time. If you work in a team, you might just cost somebody a full day of hair pulling.






          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%2f53477446%2fconverting-sql-to-arel-column-must-appear-in-the-group-by-clause%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














            So after hours of digging it turns out the big gotcha! of my problem was a default_scope set on my Order model - that's where sorting by :date was happening. In the end I decided to remove the default scope, use sorting where it was actually needed and what I was left it regarding my query was this:



            orders = Order.arel_table
            query = orders
            .where(orders[:restaurant_id].not_eq(nil))
            .project(
            orders[:restaurant_id],
            Order.arel_table[:order_number].count.as('order_count'),
            Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]).as('date_month'),
            Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]]).as('date_year'),
            )
            .group(
            orders[:restaurant_id],
            Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
            Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
            )
            .order(
            orders[:restaurant_id],
            Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), date]).desc,
            Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), date]).desc

            )
            .to_sql

            Order.find_by_sql(query)


            Lesson learnt: avoid default_scopes whenever possible. If you work alone, you're likely to forget you used it over time. If you work in a team, you might just cost somebody a full day of hair pulling.






            share|improve this answer




























              0














              So after hours of digging it turns out the big gotcha! of my problem was a default_scope set on my Order model - that's where sorting by :date was happening. In the end I decided to remove the default scope, use sorting where it was actually needed and what I was left it regarding my query was this:



              orders = Order.arel_table
              query = orders
              .where(orders[:restaurant_id].not_eq(nil))
              .project(
              orders[:restaurant_id],
              Order.arel_table[:order_number].count.as('order_count'),
              Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]).as('date_month'),
              Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]]).as('date_year'),
              )
              .group(
              orders[:restaurant_id],
              Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
              Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
              )
              .order(
              orders[:restaurant_id],
              Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), date]).desc,
              Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), date]).desc

              )
              .to_sql

              Order.find_by_sql(query)


              Lesson learnt: avoid default_scopes whenever possible. If you work alone, you're likely to forget you used it over time. If you work in a team, you might just cost somebody a full day of hair pulling.






              share|improve this answer


























                0












                0








                0







                So after hours of digging it turns out the big gotcha! of my problem was a default_scope set on my Order model - that's where sorting by :date was happening. In the end I decided to remove the default scope, use sorting where it was actually needed and what I was left it regarding my query was this:



                orders = Order.arel_table
                query = orders
                .where(orders[:restaurant_id].not_eq(nil))
                .project(
                orders[:restaurant_id],
                Order.arel_table[:order_number].count.as('order_count'),
                Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]).as('date_month'),
                Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]]).as('date_year'),
                )
                .group(
                orders[:restaurant_id],
                Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
                Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
                )
                .order(
                orders[:restaurant_id],
                Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), date]).desc,
                Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), date]).desc

                )
                .to_sql

                Order.find_by_sql(query)


                Lesson learnt: avoid default_scopes whenever possible. If you work alone, you're likely to forget you used it over time. If you work in a team, you might just cost somebody a full day of hair pulling.






                share|improve this answer













                So after hours of digging it turns out the big gotcha! of my problem was a default_scope set on my Order model - that's where sorting by :date was happening. In the end I decided to remove the default scope, use sorting where it was actually needed and what I was left it regarding my query was this:



                orders = Order.arel_table
                query = orders
                .where(orders[:restaurant_id].not_eq(nil))
                .project(
                orders[:restaurant_id],
                Order.arel_table[:order_number].count.as('order_count'),
                Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]).as('date_month'),
                Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]]).as('date_year'),
                )
                .group(
                orders[:restaurant_id],
                Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
                Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
                )
                .order(
                orders[:restaurant_id],
                Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), date]).desc,
                Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), date]).desc

                )
                .to_sql

                Order.find_by_sql(query)


                Lesson learnt: avoid default_scopes whenever possible. If you work alone, you're likely to forget you used it over time. If you work in a team, you might just cost somebody a full day of hair pulling.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 27 '18 at 8:34









                Joanna GaudynJoanna Gaudyn

                252113




                252113
































                    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%2f53477446%2fconverting-sql-to-arel-column-must-appear-in-the-group-by-clause%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

                    Tonle Sap (See)

                    I get strange results when I access the Sqlitedatabase with Unity C# via XAMPP

                    Guatemaltekische Davis-Cup-Mannschaft