On Tuesday, March 31, 2015 at 11:24:58 AM UTC-7, Andrew Burleson wrote:
>
> I've got an issue where I'd like to be able to use the result of
> group_and_count in a subquery, but that doesn't work. I'm wondering if I'm
> just doing it wrong, or if there's a different way to accomplish the same
> goal.
>
> Briefly, here's the relevant bit of my schema:
>
> service one_to_many offerings
> community one_to_many offerings
> offerings one_to_many service_orders
>
> So, in a given community, I'd like to return all the services available in
> the community grouped and ordered by the number of service orders. This
> query works like so:
>
> dataset = community.offerings_dataset.join(:service_orders, :offering_id
> => :id).group_and_count(:service_id).order(:count).reverse
>
>
> => #<Sequel::Postgres::Dataset: "SELECT \"service_id\", count(*) AS
> \"count\" FROM \"offerings\" INNER JOIN \"service_orders\" ON
> (\"service_orders\".\"offering_id\" = \"offerings\".\"id\") WHERE
> (\"offerings\".\"community_id\" = 242) GROUP BY \"service_id\" ORDER BY
> \"count\" DESC">
>
> dataset.all
>
> => [#<Offering @values={:service_id=>71, :count=>3}>,
>
> #<Offering @values={:service_id=>7, :count=>2}>,
>
> #<Offering @values={:service_id=>4, :count=>2}>,
>
> #<Offering @values={:service_id=>65, :count=>1}>,
>
> #<Offering @values={:service_id=>1, :count=>1}>]
>
>
> Now, ideally what I'd prefer to do is return a dataset like
> `Service.where(id: dataset)` This doesn't work, though, since the `select`
> clause in that query has `service_id` and `count` in it, `Service.where(id:
> dataset).all` errors with "UndefinedColumn: column 'count' does not exist".
>
In general, it's a good idea to have the SQL you want in mind. In this
case, you basically want to SELECT services.*, count(*) GROUP BY
services.*. However, that's not valid SQL (at least not SQL-92), since you
can't group by services.*. So you need to select and group by all columns
in services (services.id, ...). Something like:
dataset = community.
offerings_dataset.
join(:service_orders, :offering_id => :id).
select_group(*Service.columns.map{|c| Sequel.qualify(:services, c)})
select_append{count{}.*}.
reverse(:count)
You can't use a subquery in the WHERE clause to do what you want, because a
subquery in WHERE can't add columns to SELECT. You can use a correlated
subquery in SELECT though, so this should be an alternative:
dataset = community.
offerings_dataset.
select_append(DB[:service_orders].where(:offering_id=>:services__id).select{count{}.*}.as(:count)).
reverse(:count)
You may want to benchmark both approaches and see which performs better on
your database.
Thanks,
Jeremy
--
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.