All I'm trying to do is order posts by the number of impressions (an impression is created when someone views the post) over the past 7 days. This is my named scope
scope :popular_last_week, unscoped
.select("websites.*, COUNT(impressions.id) AS counted_impressions")
.joins("INNER JOIN impressions ON websites.id = impressions.impressionable_id")
.where("impressions.created_at >= ?", 7.days.ago)
.where(:is_published => true)
.group("websites.id")
.order("counted_impressions DESC")
("counted_impressions" is used to avoid a conflict on post record)
Yet this produces the following invalid SQL (counted_impressions is not a valid column):
SELECT COUNT(*) AS count_all, websites.id AS websites_id FROM "websites" INNER JOIN impressions ON websites.id = impressions.impressionable_id WHERE "websites"."is_published" = 't' AND (impressions.created_at >= '2013-01-11 17:48:03.954542') GROUP BY websites.id ORDER BY counted_impressions
Seems the select statement is just ignored. Where am I going wrong, or how should I do it so that the SQL statement is:
SELECT websites.*, COUNT(impressions.id) AS counted_impressions FROM "websites" INNER JOIN impressions ON websites.id = impressions.impressionable_id
WHERE "websites"."is_published" = 't' AND (impressions.created_at >= '2013-01-11 17:42:57.771777') GROUP BY websites.id ORDER BY counted_impressions DESC
Try this:
scope :popular_last_week, unscoped
.select(arel_table[Arel.star])
.select(Website.arel_table[:id].count.as("counted_impressions"))
.joins("INNER JOIN impressions ON websites.id = impressions.impressionable_id")
.where("impressions.created_at >= ?", 7.days.ago)
.where(:is_published => true)
.group("websites.id")
.order("counted_impressions DESC")
Seems like the query should be:
SELECT count(*) AS impression_count, w.id AS website_id
FROM websites as w
INNER JOIN impressions as i ON w.id = i.impressionable_id
WHERE w.is_published = 't' AND i.created_at >= '2013-01-11 17:48:03.954542'
GROUP BY w.id
ORDER BY impression_count DESC;
Seems like you could skip the join in this query and then run the "is_published" check on the next query to get the actual post data... assuming you're only using this query to get a list of ID's for a second query that gets the data.
Related
Required sort by condition - if field is exclusive, then sort by "fees"."exclusive_price" else by "fees"."additional_price".
SQL completely looks like this:
SELECT DISTINCT "numbers".*
FROM "numbers"
INNER JOIN "users_numbers" ON "users_numbers"."number_id" = "numbers"."id"
INNER JOIN "users" ON "users"."id" = "users_numbers"."user_id"
INNER JOIN "fees" ON "fees"."user_id" = "users"."id"
WHERE "numbers"."state" != 'removed'
ORDER BY CASE "numbers"."is_exclusive" WHEN TRUE THEN "fees"."exclusive_price" ELSE "fees"."additional_price" END desc"
But I get an error (in rails):
ActiveRecord::StatementInvalid: PG::InFailedSqlTransaction: ERROR: current transaction is aborted, commands ignored until end of transaction block
Error because of distinct. Without distinct - success.
How to correct SQL?
Added columns from related tables to SELECT - didn't help:
SELECT DISTINCT "fees"."exclusive_price", "fees"."additional_price", "sender_numbers".*
FROM ...
A plain DISTINCT de-duplicates based on the complete SELECT list. The (final) ORDER BY step then only accepts expressions that are part of that SELECT list.
To order by that CASE expression, you'd have to include it in the SELECT list. Like:
SELECT DISTINCT n.*, CASE WHEN n.is_exclusive THEN f.exclusive_price ELSE f.additional_price END AS order_col
FROM numbers n
JOIN users_numbers un ON un.number_id = n.id
JOIN users u ON u.id = un.user_id
JOIN fees f ON f.user_id = u.id
WHERE n.state <> 'removed'
ORDER BY order_col DESC;
You would have to wrap that in an outer query to remove order_col from the SELECT list. But I am not sure, we have the complete picture, yet. And there may be simpler ways ...
I am trying to modify an SQL statement that returns the number of Incidents logged by a user. The current statement is -
SELECT
USERS.NAME,
Count(INCIDENTS_H.SERVICEREQNO)
FROM Sostenuto.sunrise.INCIDENTS_H INCIDENTS_H
INNER JOIN Sostenuto.sunrise.USERS USERS
ON INCIDENTS_H.OWNERACCOUNT = USERS.SERVICEREQNO
WHERE (INCIDENTS_H.ADDEDDATE >= {ts '2013-11-25 00:00:00'})
AND (INCIDENTS_H.OPERATIONID = 102005166)
AND (INCIDENTS_H.OWNERGROUP = 123000012
OR INCIDENTS_H.OWNERGROUP=123000031
OR INCIDENTS_H.OWNERGROUP=123000047)
AND (INCIDENTS_H.ADDEDBY=INCIDENTS_H.OWNERACCOUNT)
GROUP BY USERS.NAME
Which works fine. Howeever I need to add another clause into the statement from a different table, I need to also include-
INCIDENTS.ADDEDBY = INCIDENTS_H.OWNERACCOUNT
However I am struggling to modify the original statement to include this. Can anyone give me any pointers?
SELECT
USERS.NAME,
Count(INCIDENTS_H.SERVICEREQNO)
FROM Sostenuto.sunrise.INCIDENTS_H INCIDENTS_H
INNER JOIN Sostenuto.sunrise.USERS USERS
ON INCIDENTS_H.OWNERACCOUNT = USERS.SERVICEREQNO
INNER JOIN INCIDENTS I
ON INCIDENTS.ADDEDBY = INCIDENTS_H.OWNERACCOUNT
WHERE (INCIDENTS_H.ADDEDDATE >= {ts '2013-11-25 00:00:00'})
AND (INCIDENTS_H.OPERATIONID = 102005166)
AND (INCIDENTS_H.OWNERGROUP = 123000012
OR INCIDENTS_H.OWNERGROUP=123000031
OR INCIDENTS_H.OWNERGROUP=123000047)
AND (INCIDENTS_H.ADDEDBY=INCIDENTS_H.OWNERACCOUNT)
GROUP BY USERS.NAME
try:
SELECT u.NAME, Count(h.SERVICEREQNO)
FROM Sostenuto.sunrise.INCIDENTS_H h
Join Sostenuto.sunrise.USERS u
ON h.OWNERACCOUNT = u.SERVICEREQNO
Join Incidents i
On i.ADDEDBY = h.OWNERACCOUNT
WHERE (h.ADDEDDATE>={ts '2013-11-25 00:00:00'})
AND (h.OPERATIONID=102005166)
AND (h.OWNERGROUP=123000012 OR h.OWNERGROUP=123000031 OR h.OWNERGROUP=123000047)
AND (h.ADDEDBY=h.OWNERACCOUNT)
GROUP BY u.NAME
I have a query that is supposed to count how many times a user has logged into two different versions of our software based on unique session ids. My count in my outer select statement however is counting way too many times. For example I get 31000 sessions for one user which is incorrect. It should be something more like 40. Why is this happening?
SELECT X.FirstName, X.LastName, X.CompanyName, X.AQ8Sessions, AQ360Sessions = COUNT(RRUI.SessionId)
FROM(
SELECT RRUI.UserId, RRUI.FirstName, RRUI.LastName, RRUI.CompanyName, COUNT(distinct RRUI.SessionId) AQ8Sessions
FROM Authentication.dbo.RegReportUserInfo RRUI
INNER JOIN Authentication.dbo.RegReportSessions RRS
ON RRUI.SessionId = RRS.SessionId
INNER JOIN WebCatalog.Published.People P
ON P.PKey = RRUI.UserId
WHERE RRUI.ClientType = 'aq8' AND RRS.ExpiresAt <= '2013-11-24 23:59:59.999'
AND RRS.ExpiresAt >= '2013-11-18 00:00:00.000' AND RRUI.CompanyName NOT LIKE 'AutoQuotes%'
AND P.EMail NOT LIKE '%#aqnet.com'
GROUP BY RRUI.FirstName, RRUI.LastName, RRUI.CompanyName, RRUI.UserId
) X
INNER JOIN Authentication.dbo.RegReportSessions RRS
ON RRS.UserId = X.UserId
AND RRS.ExpiresAt <= '2013-11-24 23:59:59.999'
AND RRS.ExpiresAt >= '2013-11-18 00:00:00.000'
LEFT OUTER JOIN Authentication.dbo.RegReportUserInfo RRUI
ON X.UserId = RRUI.UserId AND RRUI.ClientType = 'aq360'
GROUP BY X.FirstName, X.LastName, X.CompanyName, X.AQ8Sessions
ORDER BY X.AQ8Sessions DESC, COUNT(RRUI.SessionId) DESC
Hard to say for sure without seeing the data but I expect one or both of these will fix it:
COUNT(DISTINCT RRUI.SessionId)
and / or
INNER JOIN Authentication.dbo.RegReportUserInfo
where you had
LEFT OUTER JOIN Authentication.dbo.RegReportUserInfo
I have the following code in Ruby:
Comment.select("comments.*, COALESCE(SUM(votes.value), 0) AS rating,
user_votes.value AS user_value").
joins("LEFT JOIN votes ON votes.voteable_type = '"+type+"' AND votes.voteable_id = comments.id").
joins("LEFT JOIN votes AS user_votes ON user_votes.voteable_type = '"+type+"' AND user_votes.voteable_id = comments.id AND user_votes.user_id = #{user_id}").
where(conditions).group("comments.id").order("comments."+method).limit(limit).offset(offset)
When Rails generates this SQL query, it doesn't include the full select statement:
SELECT COUNT(*) AS count_all, comments.id AS comments_id FROM `comments`
LEFT JOIN votes ON votes.voteable_type = 'reply' AND votes.voteable_id = comments.id
LEFT JOIN votes AS user_votes ON user_votes.voteable_type = 'reply' AND
user_votes.voteable_id = comments.id AND user_votes.user_id = 1 WHERE (commentable_id =
1 AND commentable_type = 'Impression')
GROUP BY comments.id ORDER BY comments.rating DESC LIMIT 10 OFFSET 0
If I remove the group statement, however, then it properly includes the full select statement. What's going on?
select comments.* in your select statement conflicts with group by("comments.id").
Every column selected must either be in the GROUP BY clause or be contained in an aggregate function.
SQL Server shows error for SQL:
select c.* from tt_country c group by c.name
Column 'tt_country.country_id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
ActiveRecord and arel throws out the specified select because it is ambiguous / invalid.
SELECT course_categories.course_category_title, COUNT(*) as count
FROM course_enrollments
JOIN courses ON course_enrollments.course_id = courses.course_id
JOIN course_categories ON course_categories.id = courses.course_category_id"
GROUP BY course_categores.id
ORDER BY courses_categories.title
How would I do this in rails: (I tried the below with major errors)
category_rs = CourseEnrollment.select("course_categories.title, COUNT(*) as count").
joins(:courses, :course_categories).
group("course_categories.id").
order("course_categories.title")
I figured it out, I needed to specify the join as a string.