I'm trying to figure out why this code doesn't work; i'm trying to select "upgrades" from the database that the user doesn't already have. I've done it two ways
This Way:
SELECT id, name, cost, prereq, nullif FROM upgrades WHERE NOT IN (Select upgrade_id FROM user_upgrades WHERE uid = :uid);
and this way:
SELECT id, name, cost, prereq, nullif FROM upgrades WHERE NOT IN (:ID)
in which the :ID tag isa list of user upgrades pulled through a function in PHP. Neither one of these codes are working--they do not show any results whats so ever.
You forgot the attribute in the condition after WHERE:
WHERE "MISSING ATTRIBUTE" NOT IN ...
Related
Tag.joins(:quote_tags).group('quote_tags.tag_id').order('count desc').select('count(tags.id) AS count, tags.id, tags.name')
Build query:
SELECT count(tags.id) AS count, tags.id, tags.name FROM `tags` INNER JOIN `quote_tags` ON `quote_tags`.`tag_id` = `tags`.`id` GROUP BY quote_tags.tag_id ORDER BY count desc
Result:
[#<Tag id: 401, name: "different">, ... , #<Tag id: 4, name: "family">]
It not return count column for me. How can I get it?
Have you tried calling the count method on one of the returned Tag objects? Just because inspect doesn't mention the count doesn't mean that it isn't there. The inspect output:
[#<Tag id: 401, name: "different">, ... , #<Tag id: 4, name: "family">]
will only include things that the Tag class knows about and Tag will only know about the columns in the tags table: you only have id and name in the table so that's all you see.
If you do this:
tags = Tag.joins(:quote_tags).group('quote_tags.tag_id').order('count desc').select('count(tags.id) AS count, tags.id, tags.name')
and then look at the counts:
tags.map(&:count)
You'll see the array of counts that you're expecting.
Update: The original version of this answer mistakenly characterized select and subsequent versions ended up effectively repeating the current version of the other answer from #muistooshort. I'm leaving it in it's current state because it has the information about using raw sql. Thanks to #muistooshort for pointing out my error.
Although your query is in fact working as explained by the other answer, you can always execute raw SQL as an alternative.
There are a variety of select_... methods you can choose from, but I would think you'd want to use select_all. Assuming the build query that you implicitly generated was correct, you can just use that, as in:
ActiveRecord::Base.connection.select_all('
SELECT count(tags.id) AS count, tags.id, tags.name FROM `tags`
INNER JOIN `quote_tags` ON `quote_tags`.`tag_id` = `tags`.`id`
GROUP BY quote_tags.tag_id
ORDER BY count desc')
See http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/DatabaseStatements.html for information on the various methods you can choose from.
I have a table 'users_category'
'users_category' : id, prefix, name
and table 'users'
'users' : categories, etc...
where users.categories is an array of users_category.id ids
User can be part of any category, if I stored the array of categories they are part of as a serialized array, how can I run a query to check if they are part of 'category x'
Ex:
SELECT users.*, users_category.* FROM 'users', 'users_category' WHERE users.categories='category x' AND users_category.id = 'category x'
I can't run a 'LIKE' command because the users.categories is serialized. Is their any way to search within the serialized data. Also I know that the above query may have errors
Even though normalizing the table structure is a better way to move forward but if adopting that route is not optimal at this point then you may try this query:
SELECT u.*, uc.*
FROM users u, users_category uc
WHERE uc.name='X' AND FIND_IN_SET(uc.id, u.categories)
It uses mysql function FIND_IN_SET().
Working demo available at: http://sqlfiddle.com/#!2/7f392/3
I have the following query:
SELECT routes.route_date, time_slots.name, time_slots.openings, time_slots.appointments
FROM routes
INNER JOIN time_slots ON routes.route_id = time_slots.route_id
WHERE route_date
BETWEEN 20140109
AND 20140115
AND time_slots.openings > time_slots.appointments
ORDER BY route_date, name
This works just fine and will produce the following results:
What I want to do is only return one name per date. So the 9th, name = 1, would only have 1 result, rather than 2, as it currently does.
UPDATE: See the SQLFIDDLE for different type of solutions here: http://sqlfiddle.com/#!2/9ac65b/6
Will it solve your request if you use...
SELECT DISTINCT routes.route_date...your query... ?
It depends if you know that your rows always will have the same values, for same date/name.
Otherwise use group by...
(which I think suits your request best)
SELECT routes.route_date, time_slots.name, sum(time_slots.openings), sum(time_slots.appointments)
FROM routes
INNER JOIN time_slots ON routes.route_id = time_slots.route_id
WHERE route_date
BETWEEN 20140109
AND 20140115
AND time_slots.openings > time_slots.appointments
group by routes.route_date, time_slots.name
ORDER BY route_date, name
(i did a sum for the openings and appointments, you could do min, max, count, etc. Pick the one that fits your requirements best!)
You need to figure out which "name" you want when there are several for the same date.
Then you can group by date and select the right "name" by using an aggregate function like COUNT, MAX, etc.
I can't help you more if you don't explain your rule for picking one.
With Rails 3, I am using the following kind of code to query a MySQL database:
MyData.joins('JOIN (SELECT id, name FROM sellers) AS Q
ON seller_id = Q.id').
select('*').
joins('JOIN (SELECT id, name FROM users) AS T
ON user_id = T.id').
select("*").each do |record|
#..........
Then, a bit further down, I try to access a "name" with this code: (note that both sellers and users have a name column).
str = record.name
This line is giving me a "user name" instead of a "seller name", but shouldn't it give nothing? Since I joined multiple tables with a name column, shouldn't I be get an error like "column 'name' is ambiguous"? Why isn't this happening?
And by the way, the code behaves the same way whether I include that first "select('*')" line or not.
Thank you.
Firstly, there's no reason to call select twice - only the last call will actually be used. Secondly, you should not be using select("*"), because the SQL database (and Rails) will not rename the ambiguous columns for you. Instead, use explicit naming for the extra columns that you need:
MyData.joins('JOIN (SELECT..) AS Q ON ...', 'JOIN (SELECT...) AS T ON ...').
select('my_datas.*, T.name as t_name, Q.name as q_name').
each do |record|
# do something
end
Because of this, there's no reason to make a subquery in your JOIN statements:
MyData.joins('JOIN sellers AS Q ON ...', 'JOIN users AS T ON ...').
And finally, you should already have belongs_to associations set up for seller and user. That would mean that you can just do this:
MyData.joins(:seller, :user).
select("my_datas.*, sellers.name as seller_name, users.name as user_name").
each do |record|
# do something
end
Now you can call record.seller_name and record.user_name without any ambiguity.
I'm trying to get the rank of an activerecord object based on the number of votes its currently received. In my object model, I have a method 'rank' defined as:
Object.count(:conditions => ['votes > (?)', self.votes], :distinct => true) + 1
That returns the rank. However, elsewhere in my program I have found that I actually need to get this in the mysql query itself. I wanted to try to do something like below:
Object.select('id, votes, (SELECT COUNT(DISTINCT "objects"."id")
FROM "objects"
WHERE "objects"."votes" > votes) AS rank').limit(10)
However, I dont know how to do the 'objects.votes > votes' part. I need to replace '> votes', with some reference to itself. Not sure if that's clear. Any ideas?
I will guess that you mean, how do you pass self.votes from rails to the SQL query?
You can do this:
Object.where("votes > ?",self.votes)
So to pass self.votes to your query:
Object.select('id, votes, (SELECT COUNT(DISTINCT "objects"."id")
FROM "objects"
WHERE "objects"."votes" > ?) AS rank',self.votes).limit(10)