How can I get unique values from column in the table? For example, I have this Products table:
user_id number
1 900
1 400
2 100
2 300
3 200
Here I used....
like so
Post.order(number: :desc).limit(3).each do |p| > I got here
user_id number
1 900
1 400
2 300
like so
Here I want "user_id" not to overlap. like this
f
user_id number
1 900
2 300
3 200
As deepak adviced, you might use distinct.
However, I guess you need to get maximum value from all records with the same user_id? Then you need to use sql to group values by user_id and selecting max from it. In Rails that might be like this. I can't tell you that it will work for sure because don't remember the output, believe it's array of hashes, it might throw the error that you're not using some other field:
Post.group(:user_id).max(:value)
it's SQL equalent:
SELECT user_id, MAX(value) FROM posts GROUP BY user_id
Related
I'm using the ajax datatable gem to display the client name and total points in a store. the store-clients table looks like this.
store_id
client_id
total_points
But as it will be a report, I don't want to show the same client twice, even to different stores. I am trying the following:
StoreClient.joins(:client).group(:client_id)
But I get this error: column "store_clients.id" must appear in the GROUP BY clause or be used in an aggregate function
If I add the store_clients id the result is not as expected.
The expected would be:
client_id | store_id | total_points
1 1 10
1 2 20
2 1 5
-----------------------------------
client_id | store_id | total_points
1 1 10
2 1 5
Assume initial result is an array store in instance variable #result you can get a unique result like this:
#result.uniq {|o| o.client_id }
I have the following structure:
User model: id, ..
Event model: id, ..
UserMapEvent model: user_id, event_id
For example the UserMapEvent table might have the following records:
User_id | Event_id
1 | 1
1 | 2
3 | 1
4 | 1
I'm using this structure to save when a user likes an event.
Now, if I'm in the shows controller and I know the event's id, I can get the number of times the user liked the event like:
`likes = UsersMapEvent.where("event_id = ?", event.id).count`
How do I get, for example, the top 3 liked events? Do I have to join the 2 tables?
The only solution that I could think of is to use Event.all and for each to do the exact same thing, but it sounds stupid and I assume this is not one of those cases 'if it's stupid and it works is fine'.
What type of database operation do I have to use to get my query?
You may select top 3 liked events with next code:
Event.left_joins(:users_map_events).group(:id).order('COUNT(users_map_events.id) DESC').limit(3)
I have a table called lead, which have about 500 thousand records and we need the following query to get executed.
SELECT skip 300000 first 75 *
FROM lead
WHERE ((enrollment_period IS NULL) OR
(enrollment_period IN ('FT2015','F16','SUM2016','FALL2016','FALL2017','SP17')))
ORDER BY created_on DESC
The table lead has id column as the primary key and thus have clustered index in that column. This query is taking about 12 - 13 mins. When I added a non-clustered index on created_on and enrollment_period columns, it came down to 4 - 5 mins. Then I changed the clustered index from id column to this index, execution time came down further to about 50 seconds now.
Is there any other optimization scope available for this query?
Overall, is there any other change that can be done so that the query will execute faster?
Thanks in Advance,
Manohar
So I have a standard users table structure, with a primary id key and what so not and the following persona table:
user_id | persona_id | time_inserted
2 1 x
2 2 x+1
2 3 x+2
1 1 x+3
5 8 x+6
5 9 x+1
What I'd like to do is retrieve the LAST inserted row and limit to ONE per user id. So, in that query, the result I want would be:
[2, 3] because the last inserted for 2 was persona_id 3 (x+2), [1, 1], and [5,8] because the last inserted for 5 was persona_id 8 (x+6)
This is my query:
to_return = Persona.select(to_get).where(to_condition)
This works, but retrieves them all. How can I restrict the query as asked? Thank you very much.
This should work:
to_return = Persona.select(to_get).where(to_condition).group('user_id').having('time_inserted = MAX(time_inserted)')
Update
You can't select a column if you don't put that in the group clause.
As you want to group by only user_id, one possible solution is, select the user_id s first with the maximum time_inserted like this:
users_ids_relation = Persona.select('user_id').group('user_id').having('time_inserted = MAX(time_inserted)')
Then, join it with the personas table based on the condition and then select the required columns:
users_ids_relation.joins('personas').where(to_condition).select(to_get)
It will give you the expected result.
user = SkillUser.find_all_by_skill_id(skill_id)
user.size
gives me: 1 2 2 1 3 1 3 1 3 2 1 1 3
How can I get the biggest value (in this case 3) out of this row of numbers?
Thanks for help
You can use the maximum scope on your ActiveRelation:
SkillUser.maximum(:rating)
If you want the maximum of an attribute called rating.
If you want to count the number of users per skill id, try:
SkillUser.count(:group => :skill_id).max_by { |skill_id,count| count }
This gives you both the skill_id and the number of users for the skill with most users.
For a more efficient way (by doing the whole calculation in SQL), try:
SkillUser.limit(1).reverse_order.count(:group => :skill_id, :order => :count)
# Giving the SQL:
# => SELECT COUNT(*) AS count_all, "skill_users"."skill_id" AS skill_id
# FROM "skill_users" GROUP BY "skill_users"."skill_id"
# ORDER BY "skill_users"."count" DESC LIMIT 1
Be aware that count must be called last because it doesn't return an ActiveRelation for you to further scope the query.
You should use ActiveRecord::Calculations
http://ar.rubyonrails.org/classes/ActiveRecord/Calculations/ClassMethods.html
for performance reasons
1.9.3-194 (main):0 > User.maximum(:id)
(1.6ms) SELECT MAX("users"."id") AS max_id FROM "users"
=> 3
Fastest way to find a single maximum value in an unsorted list of
integer is to scan the list from left to right and memorize the
largest value so far.
If you sort the list first, you get the
additional benefit of easily finding the 2nd, 3rd etc. largest
values easily as well.
If you take one of the "maximum" methods hidden in ruby ... you should check what the implementors are doing to pick the max and compare it to 1. and 2. above :-)
Explanations:
to 1. Doing it this way, you just have to pick each value in the list exactly once and compare it once to the maximum so-far.
to 2. Sorting costs O(n*log n) ops in the average if you got a list with n entries. Obviously this is more than the O(n) in solution 1., but you get a bit more
to 3. Well.. I prefer knowing what happens, but your preferences might vary