Rails - Get Column Value with Group By - ruby-on-rails

I have the following tables with entries that might look like:
Table: sessions
ID | CREATED_AT | UPDATED_AT | USER_ID | GROUP_ID
---|-------------------------|-------------------------|---------|----------
27 | 2014-07-01 23:02:16 | 2014-07-01 23:03:18 | 1 | 1
28 | 2014-07-02 16:55:25 | 2014-07-02 17:31:40 | 1 | 2
29 | 2014-07-07 20:31:13 | 2014-07-07 20:34:17 | 1 | 3
Table: groups
ID | NAME | CREATED_AT | UPDATED_AT
---|-------------------|-------------------------|------------------------
1 | Marching | 2013-12-17 19:45:28 | 2013-12-17 19:45:28
2 | Reaching | 2014-02-07 17:29:59 | 2014-02-07 17:29:59
3 | Picking | 2014-03-11 21:38:56 | 2014-03-11 21:38:56
And I have the following query in Rails:
Session.joins(:group).select('groups.name').where(:user_id => 1).group('sessions.group_id').count
Which returns the following keys and values:
=> {2=>7, 1=>3, 3=>1} (The "key" is the group_id and the "value"
is the # of times it occurs).
My question is: Instead of returning the "id" as the key, is it possible for me to return the groups.name instead? Which would look like:
=> {"Reaching"=>7, "Marching"=>3, "Picking"=>1}
If not, would I have to loop through and re-query again based on each group_id?
Thanks very much.

This should work if you have everything set up in your models.
data = Group.joins(:sessions).select('name, count(*) as occurrence_count').where('sessions.user_id = ?', 1).group('groups.name')
Then you can access it like this
data.first.occurrence_count

Related

Ruby - Convert SQL unnest to Arel

How can I convert the following query into Arel? I want to define a where condition using arel.
select * from tenants where id in (select a.id::int from tenants t2 cross join unnest(string_to_array(t2.ancestry, '/')) as a(id) where t2.id = 39);
Here is how the table output looks like:
-[ RECORD 1 ]-------------+------------------
id | 39
domain |
subdomain |
name | Child_Teanant_201
login_text |
logo_file_name |
logo_content_type |
logo_file_size |
logo_updated_at |
login_logo_file_name |
login_logo_content_type |
login_logo_file_size |
login_logo_updated_at |
ancestry | 1/35
divisible | t
description | Child_Teanant_201
use_config_for_attributes | f
default_miq_group_id | 51
source_type |
source_id |

How to correct query object to shows data properly in Rails 5

I need some fresh eye to my object query. The idea is to show from db all users which have only one client (belongs_to :user), which are not subscribed.
models
user
has_many :customers
has_many :customers_users
customer
has_many :customers_users
belongs_to :user
customers_user
belongs_to :user
belongs_to :customer
customer_subscription
belongs_to :customer
query
Customer.
joins("LEFT JOIN customer_subscriptions ON customer_subscriptions.customer_id = customers.id").
where(customer_subscriptions: { id: nil }).
joins("RIGHT JOIN customers_users ON customers_users.customer_id = customers.id").
group(:user_id).
having("count(user_id) = ?", 1).
count
But after all I've got only user_id without data such as name, email, nickname etc. I thought the problem is with count at the end but without count I received an error NoMethodError: undefined method 'having' for main:Object
Is it possible to reach these data in one query?
In your case I guess a negative condition in the join would work. So the query would be like:
SELECT * FROM users
INNER JOIN customers
ON customers.user_id = users.id
INNER JOIN customers_subscriptions
ON customers_subscriptions.customer_id != customers.user_id
GROUP BY users.id
HAVING COUNT(users.id) = 1
So having:
Users:
+----+-------+------------+----------------------------+----------------------------+
| id | email | name | created_at | updated_at |
+----+-------+------------+----------------------------+----------------------------+
| 1 | NULL | seb | 2019-04-27 19:16:09.043251 | 2019-04-27 19:16:09.043251 |
| 2 | NULL | sab | 2019-04-27 19:16:09.150315 | 2019-04-27 19:16:09.150315 |
| 3 | NULL | washington | 2019-04-27 19:58:01.737446 | 2019-04-27 19:58:01.737446 |
+----+-------+------------+----------------------------+----------------------------+
Customers:
+----+------------+-------+---------+----------------------------+----------------------------+
| id | name | email | user_id | created_at | updated_at |
+----+------------+-------+---------+----------------------------+----------------------------+
| 1 | Sab | NULL | 1 | 2019-04-27 19:16:09.254955 | 2019-04-27 20:02:47.636143 |
| 2 | Seb | NULL | 2 | 2019-04-27 19:16:09.313268 | 2019-04-27 20:02:55.741603 |
| 3 | Washington | NULL | 3 | 2019-04-27 19:58:22.711897 | 2019-04-27 19:58:45.213720 |
| 4 | Eminem | NULL | 3 | 2019-04-27 19:58:52.820731 | 2019-04-27 20:03:02.465681 |
+----+------------+-------+---------+----------------------------+----------------------------+
Customers Subscriptions:
+----+-------------+----------------------------+----------------------------+
| id | customer_id | created_at | updated_at |
+----+-------------+----------------------------+----------------------------+
| 1 | 1 | 2019-04-27 19:16:10.041788 | 2019-04-27 19:16:10.041788 |
| 2 | 3 | 2019-04-27 20:04:16.464446 | 2019-04-27 20:04:16.464446 |
+----+-------------+----------------------------+----------------------------+
The result should be:
+----+-------+------+----------------------------+----------------------------+----+------+-------+---------+----------------------------+----------------------------+----+-------------+----------------------------+----------------------------+
| id | email | name | created_at | updated_at | id | name | email | user_id | created_at | updated_at | id | customer_id | created_at | updated_at |
+----+-------+------+----------------------------+----------------------------+----+------+-------+---------+----------------------------+----------------------------+----+-------------+----------------------------+----------------------------+
| 1 | NULL | seb | 2019-04-27 19:16:09.043251 | 2019-04-27 19:16:09.043251 | 1 | Sab | NULL | 1 | 2019-04-27 19:16:09.254955 | 2019-04-27 20:02:47.636143 | 2 | 3 | 2019-04-27 20:04:16.464446 | 2019-04-27 20:04:16.464446 |
+----+-------+------+----------------------------+----------------------------+----+------+-------+---------+----------------------------+----------------------------+----+-------------+----------------------------+----------------------------+
So an AR code for that could be:
User.
joins(:customers).
joins('INNER JOIN customers_subscriptions ON customers_subscriptions.customer_id != customers.user_id').
group(:id).
having('COUNT(users.id) = 1')

How I can count the total votes in worker table in Rails [duplicate]

This question already has answers here:
Rails has_many association count child rows
(5 answers)
Closed 8 years ago.
I'am confused when I try to count the total votes in my votes table in rails..
serviceproviders has_many votes
votes belongs_to serviceproviders
I tried like this :
sp = Serviceprovider.joins(:votes).group_by(&:id).count
but it doesn't get the right output.
example output I want is:
If in the table Jhon Doe has 5 row of votes in the table, I can get the total 5 votes when I query. Can any give me the idea how can execute the query. Thank you!
Update:
Thank you for those answers.
I tried this in my rails c.
vote = Vote.joins(:serviceprovider).group(:serviceprovider_id).count
and I got the results: {108=>2, 109=>1}
My question how can I get the top 10 highest votes?
Here is the table:
app_development=# select * from votes;
id | city | created_at | updated_at | service_provider_id
----+---------+----------------------------+----------------------------+---------------------
1 | B\'lore | 2015-02-19 17:35:58.061324 | 2015-02-19 17:35:58.083479 | 3
2 | Kol | 2015-02-19 17:35:58.103013 | 2015-02-19 17:35:58.123405 | 2
3 | Mum | 2015-02-19 17:35:58.11242 | 2015-02-19 17:35:58.125345 | 2
4 | Kochin | 2015-02-19 17:35:58.136139 | 2015-02-19 17:35:58.167971 | 1
5 | Mum | 2015-02-19 17:35:58.145833 | 2015-02-19 17:35:58.170319 | 1
6 | Chennai | 2015-02-19 17:35:58.156755 | 2015-02-19 17:35:58.171996 | 1
(6 rows)
app_development=# select * from service_providers;
id | name | created_at | updated_at
----+------+----------------------------+----------------------------
1 | MTS | 2015-02-19 17:35:57.837508 | 2015-02-19 17:35:57.837508
2 | HCL | 2015-02-19 17:35:57.923479 | 2015-02-19 17:35:57.923479
3 | ACL | 2015-02-19 17:35:57.934414 | 2015-02-19 17:35:57.934414
You need the following query to obtain the desired result :
Vote.joins(:service_provider)
.group(:service_provider_id)
.order("count_all desc")
.limit(10)
.count
Tested in Rails console :
[arup#app]$ rails c
Loading development environment (Rails 4.1.1)
[1] pry(main)> Vote.joins(:service_provider).group(:service_provider_id).order("count_all desc").limit(2).count
(2.0ms) SELECT COUNT(*) AS count_all, service_provider_id AS service_provider_id FROM "votes" INNER JOIN "service_providers" ON "service_providers"."id" = "votes"."service_provider_id" GROUP BY service_provider_id ORDER BY count_all desc LIMIT 2
=> {1=>3, 2=>2}
[2] pry(main)>
Try this
sp = ServiceProvider.find_by_name("Jhon Doe");
#votes = sp.votes.count

How to join with a polymorphic model using the PublicActivity gem

I'm using the PublicActivity gem: https://github.com/pokonski/public_activity
All of the models I use PublicActivity to track use the column edition_id. And I'm wondering how I can scope by that column since it's polymorphic relation.
Eg PublicActivity looks like so:
PublicActivity::Activity.limit(50)
+----+--------------+----------------+----------+------------+--------------------+------------+--------------+----------------+---------------------------+---------------------------+
| id | trackable_id | trackable_type | owner_id | owner_type | key | parameters | recipient_id | recipient_type | created_at | updated_at |
+----+--------------+----------------+----------+------------+--------------------+------------+--------------+----------------+---------------------------+---------------------------+
| 1 | 42 | QuizMaster | 6 | User | quiz_master.update | {} | | | 2013-04-12 17:33:14 +0100 | 2013-04-12 17:33:14 +0100 |
| 2 | 25 | Place | 6 | User | place.update | {} | | | 2013-04-12 17:42:42 +0100 | 2013-04-12 17:42:42 +0100 |
| 3 | 25 | Event | 6 | User | event.update | {} | | | 2013-04-12 17:45:08 +0100 | 2013-04-12 17:45:08 +0100 |
| 4 | 20 | QuizMaster | 6 | User | quiz_master.update | {} | | | 2013-04-12 17:49:09 +0100 | 2013-04-12 17:49:09 +0100 |
| 5 | 20 | QuizMaster | 6 | User | quiz_master.update | {} | | | 2013-04-12 17:50:51 +0100 | 2013-04-12 17:50:51 +0100 |
+----+--------------+----------------+----------+------------+--------------------+------------+--------------+----------------+---------------------------+---------------------------+
Where edition_id is on the polymorphic trackable relation.
What I would like to do it something like:
PublicActivity::Activity.limit(50).includes(:trackable)# where trackable edition = 1
I'm not sure how or even if it's possible to join or include or preload a polymorphic model across multiple "trackable" types.
I don't think this is possible directly with SQL because of the polymorphism, but you could do something with ruby pretty easily.
PublicActivity::Activity.limit(50).select {|c| c.trackable.edition_id = 1 }
It won't be as efficient as a SQL query but using Rails preload it'll probably be good enough depending on the number of records you're fetching.
PublicActivity::Activity.limit(50).preload(:trackable).select {|c| c.trackable.edition_id = 1 }

Rails fetch row with latest update

I have such db table structure:
id | currency_list_id | direction_id | value | updated_at
and i have such data:
1 | 1 | 1 | 8150 | 09-08-2010 01:00:00
1 | 1 | 2 | 8250 | 09-08-2010 01:00:00
1 | 2 | 1 | 8150 | 06-08-2010 01:00:00
1 | 2 | 2 | 8150 | 06-08-2010 01:00:00
1 | 1 | 1 | 8150 | 09-08-2010 15:00:00
1 | 1 | 2 | 8250 | 09-08-2010 15:00:00
so currency in exchanger is setted almost everyday, and could be setted more than one time in a day.... but also one could be setted some days ago... And i must to fetch all actual data..
How in rails (ruby) i could fetch only last actual data?
In my example result will be:
1 | 2 | 1 | 8150 | 06-08-2010 01:00:00
1 | 2 | 2 | 8150 | 06-08-2010 01:00:00
1 | 1 | 1 | 8150 | 09-08-2010 15:00:00
1 | 1 | 2 | 8250 | 09-08-2010 15:00:00
how to do this?
i try so:
#currencies = CurrencyValue.find(:all, :conditions => {:currency_list_id => id}, :order => :updated_at)
but then i will fetch all data for some currency_list_id with ordering, but how to fetch only last 2 values? How to fetch last 2 ordered rows?
#currencies = CurrencyValue.find(:all, :conditions => {:currency_list_id => id, :order => :updated_at}).last(2)
I think :). Can't check this right now.
I think what you need by be a GROUP_BY. There's another question that explains it here:
How to get the latest record in each group using GROUP BY?

Resources