Add a variable in syntax - mysql

In this example which runs here live
I would like to add the user id in the retrieved data
I use this
;with postvotes as
(
select v.creationdate,
v.userid
, p.id postid
, case v.votetypeid
when 1 then 'accepts'
when 2 then 'up-votes'
when 3 then 'down-votes'
when 9 then 'bounty_recieved'
end vote_type
, case p.posttypeid
when 1 then 'question'
when 2 then 'answer'
end post_type
, sum(case v.votetypeid
when 1 then 15
when 2 then 10
when 3 then -2
when 9 then bountyamount
end
) reputation_change
from votes v
inner join posts p on p.id = v.postid
where p.owneruserid = ##userid?1719510##
and posttypeid in (1,2)
and votetypeid in (1,2,3,9)
group by v.creationdate, p.id, votetypeid, posttypeid
),
bounties as
(
select v.creationdate
, v.postid postid
, 'bounty-offered' vote_type
, 'question' post_type
, sum(bountyamount) reputation_change
from votes v
where v.userid = ##userid?1719510##
and votetypeid = 8
group by v.creationdate, v.postid, votetypeid
),
approvededits as
(
select se.creationdate
, se.postid postid
, 'approved-edit' vote_type
, case p.posttypeid
when 1 then 'question'
when 2 then 'answer'
end post_type
, sum(2) reputation_change
from suggestededits se
inner join posts p on p.id = se.postid
where se.Owneruserid = ##userid?1719510##
and approvaldate is not null
group by se.creationdate, se.postid, posttypeid
)
select *
from postvotes
union
select *
from bounties
union
select *
from approvededits
But I receive this error:
Column 'votes.UserId' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
How can I fix it?

You forgot to add userid in your group by list. So your updated query might look like -
;with postvotes as
(
select v.creationdate,
, p.id postid
, case v.votetypeid
when 1 then 'accepts'
when 2 then 'up-votes'
when 3 then 'down-votes'
when 9 then 'bounty_recieved'
end vote_type
, case p.posttypeid
when 1 then 'question'
when 2 then 'answer'
end post_type
, sum(case v.votetypeid
when 1 then 15
when 2 then 10
when 3 then -2
when 9 then bountyamount
end
) reputation_change
from votes v
inner join posts p on p.id = v.postid
where p.owneruserid = ##userid?1719510##
and posttypeid in (1,2)
and votetypeid in (1,2,3,9)
group by v.creationdate, p.id, votetypeid, posttypeid
),
bounties as
(
select v.creationdate
, v.postid postid
, 'bounty-offered' vote_type
, 'question' post_type
, sum(bountyamount) reputation_change
from votes v
where v.userid = ##userid?1719510##
and votetypeid = 8
group by v.creationdate, v.postid, votetypeid
),
approvededits as
(
select se.creationdate
, se.postid postid
, 'approved-edit' vote_type
, case p.posttypeid
when 1 then 'question'
when 2 then 'answer'
end post_type
, sum(2) reputation_change
from suggestededits se
inner join posts p on p.id = se.postid
where se.Owneruserid = ##userid?1719510##
and approvaldate is not null
group by se.creationdate, se.postid, posttypeid
)
select *
from postvotes
union
select *
from bounties
union
select *
from approvededits

Related

how to get records and avoid subquery

Hi I want to avoid sub query because it working perfect for right now but it will slow in future.
SELECT
u.`id` ,
u.first_name,
u.last_name,
u.username,
( SELECT COUNT(*) FROM `complaint` AS p_c WHERE p_c.landlord_id = u.`id` AND p_c.complaint_id = 1 ) AS party_complaints,
( SELECT COUNT(*) FROM `complaint` AS r_c WHERE r_c.landlord_id = u.`id` AND r_c.complaint_id = 2 ) AS robery_complaints,
( SELECT COUNT(*) FROM `complaint` AS f_c WHERE f_c.landlord_id = u.`id` AND f_c.complaint_id = 3 ) AS fight_complaints,
( SELECT COUNT(*) FROM `complaint` AS o_c WHERE o_c.landlord_id = u.`id` AND o_c.complaint_id = 4 ) AS other_complaints,
COUNT(c.`id`) AS total_complaints_count
FROM
`user` AS u
INNER JOIN complaint AS c
ON c.`landlord_id` = u.`id`
GROUP BY u.`id`
id first_name last_name username party_complaints robery_complaints fight_complaints other_complaints total_complaints_count
------ ---------- --------- --------- ---------------- ----------------- ---------------- ---------------- ------------------------
3591 John Doe thefeature 0 13 3 2 18
4607 John Cena 10Fe416l 2 1 0 1 4
You could use a sum on case
SELECT
u.`id` ,
u.first_name,
u.last_name,
u.username,
sum( case when c.landlord_id = u.`id` and c.complaint_id = 1 then 1 else 0 end) party_complaints,
sum( case when c.landlord_id = u.`id` and c.complaint_id = 2 then 1 else 0 end) robery_complaints,
sum( case when c.landlord_id = u.`id` and c.complaint_id = 3 then 1 else 0 end) fight_complaints,
sum( case when c.landlord_id = u.`id` and c.complaint_id = 4 then 1 else 0 end) other_complaints
COUNT(c.`id`) AS total_complaints_count
FROM
`user` AS u
INNER JOIN complaint AS c
ON c.`landlord_id` = u.`id`
GROUP BY u.`id`

SQL MULTIPLE COUNT AND JOIN

I'm trying to do something like this:
User_guid | Post Message | Discussion board | Total |
1 | 300 | 25 | 325 |
2 | 15 | 185 | 200 |
3 | 100 | 203 | 303 |
but I don't know how.
I have the Post Message result with this Query:
SELECT COUNT( * ) as 'Quantidade' , users_entity.name , users_entity.username
FROM river
JOIN users_entity
ON river.subject_guid = users_entity.guid
AND river.action_type = 'create'
AND river.view = 'river/object/thewire/create'
GROUP BY river.subject_guid ORDER BY 'Quantidade' DESC
and I have the Discussion result with this Query:
SELECT COUNT( * ) as 'Quantidade' , users_entity.name , users_entity.username
FROM river
JOIN users_entity
ON river.subject_guid = users_entity.guid
AND river.action_type = 'reply'
GROUP BY river.subject_guid ORDER BY 'Quantidade' DESC
But I don't know how to join these results as rows of the users_entity table. The total interactions should be the sum of the post message and discussion board values. Someone can help me? Thanks.
It's hard to tell without table structures and sample data (which is why you're getting the down votes), but you probably need something like this:
SELECT
users_entity.name,
users_entity.username,
COUNT(CASE WHEN river.action_type = 'create' AND river.view = 'river/object/thewire/create' THEN 1 END) AS Post_Message,
COUNT(CASE WHEN river.action_type = 'reply' THEN 1 END) AS Discussion_Board
FROM river
JOIN users_entity ON users_entity.guid = river.subject_guid
GROUP BY
users_entity.name,
users_entity.username
ORDER BY ???
I'm not sure which value you want to ORDER BY with the combined query.
Maybe this works for you:
SELECT data1.username, data1.count1, data2.count2, data1.count1+data2.count2 from
(
SELECT COUNT( * ) as 'count1' , users_entity.name , users_entity.username
FROM river
JOIN users_entity
ON river.subject_guid = users_entity.guid
AND river.action_type = 'create'
AND river.view = 'river/object/thewire/create'
GROUP BY river.subject_guid ORDER BY 'Quantidade' DESC
) data1,
(
SELECT COUNT( * ) as 'count2' , users_entity.name , users_entity.username
FROM river
JOIN users_entity
ON river.subject_guid = users_entity.guid
AND river.action_type = 'reply'
GROUP BY river.subject_guid ORDER BY 'Quantidade' DESC) data2 where data1.username = data2.username
You could try joining the two queries like this
SELECT river_create.Quantidade AS create_q, river_reply.Quantidade AS reply_q, river_create.full_name, river_create.u_name, river_create.user_id
FROM
(SELECT COUNT( * ) as 'Quantidade' , users_entity.name AS full_name, users_entity.username AS u_name, users_entity.guid AS user_id
FROM river
JOIN users_entity
ON river.subject_guid = users_entity.guid
AND river.action_type = 'create'
AND river.view = 'river/object/thewire/create'
GROUP BY river.subject_guid ORDER BY 'Quantidade' DESC) AS river_create
INNER JOIN
(SELECT COUNT( * ) as 'Quantidade' , users_entity.name , users_entity.username, users_entity.guid as reply_user_id
FROM river
JOIN users_entity
ON river.subject_guid = users_entity.guid
AND river.action_type = 'reply'
GROUP BY river.subject_guid ORDER BY 'Quantidade' DESC) AS river_reply
ON river_create.user_id = river_reply.reply_user_id

MySQL "Trending"

I'm selecting "ideas" from my database currently, but another requirement is to be able to grab "trending ideas", that is, the top 10 most-up-voted ideas within the last 7 days.
My query for selecting "ideas" is this:
SELECT
t.id AS 'id',
CONCAT(t.first_name, ' ', SUBSTRING(t.last_name,1,1)) AS 'name',
t.votes_up,
t.votes_down,
t.votes_aggregate,
GROUP_CONCAT(DISTINCT tags.name) AS 'tags',
t.createdon AS 'timestamp'
FROM (
SELECT
ideas.id, first_name, last_name, createdon,
COALESCE(SUM(case when value > 0 then value end),0) votes_up,
COALESCE(SUM(case when value < 0 then value end),0) votes_down,
COALESCE(SUM(value),0) votes_aggregate
FROM ideas
LEFT JOIN votes ON ideas.id = votes.idea_id
GROUP BY ideas.id
) as t
LEFT JOIN tags_rel ON t.id = tags_rel.idea_id
LEFT JOIN tags ON tags_rel.tag_id = tags.id
How would I get and display all the votes, but only get the "ideas" that have been voted up (votes_up) within the last 7 days and ordered by the amount of votes_up ?
This is my attempt:
SELECT
t.id AS 'id',
CONCAT(t.first_name, ' ', SUBSTRING(t.last_name,1,1)) AS 'name',
t.votes_up,
t.votes_down,
t.votes_aggregate,
GROUP_CONCAT(DISTINCT tags.name) AS 'tags',
t.createdon AS 'timestamp'
FROM (
SELECT
ideas.id, first_name, last_name, createdon,
COALESCE(SUM(case when value > 0 then value end),0) votes_up,
COALESCE(SUM(case when value < 0 then value end),0) votes_down,
COALESCE(SUM(value),0) votes_aggregate
FROM ideas
LEFT JOIN votes ON ideas.id = votes.idea_id
GROUP BY ideas.id
) as t
LEFT JOIN tags_rel ON t.id = tags_rel.idea_id
LEFT JOIN tags ON tags_rel.tag_id = tags.id
WHERE t.published = 1
AND (
SELECT ideas.id,
COALESCE(SUM(case when value > 0 then value end),0) votes_up
FROM ideas
LEFT JOIN votes ON ideas.id = votes.idea_id
WHERE votes.`timestamp` > (NOW() - INTERVAL 7 DAY)
GROUP BY ideas.id
) as v
GROUP BY t.id
ORDER BY v.votes_up DESC
But I get the error for the right syntax to use near 'as v GROUP BY t.id ORDER BY v.votes_up DESC LIMIT 10'
You're using the 'AS v' in a WHERE clause, which isn't possible:
WHERE t.published = 1
AND (
SELECT ideas.id,
COALESCE(SUM(case when value > 0 then value end),0) votes_up
FROM ideas
LEFT JOIN votes ON ideas.id = votes.idea_id
WHERE votes.`timestamp` > (NOW() - INTERVAL 7 DAY)
GROUP BY ideas.id
) as v
Try this one, in your SELECT statement you do the subquery, in your WHERE you check if this isn't NULL and you can order by it (if i'm right):
SELECT
t.id AS 'id',
CONCAT(t.first_name, ' ', SUBSTRING(t.last_name,1,1)) AS 'name',
t.votes_up,
t.votes_down,
t.votes_aggregate,
GROUP_CONCAT(DISTINCT tags.name) AS 'tags',
t.createdon AS 'timestamp',
(
SELECT ideas.id,
COALESCE(SUM(case when value > 0 then value end),0) votes_up
FROM ideas
LEFT JOIN votes ON ideas.id = votes.idea_id
WHERE votes.`timestamp` > (NOW() - INTERVAL 7 DAY)
GROUP BY ideas.id
) AS vup
FROM (
SELECT
ideas.id, first_name, last_name, createdon,
COALESCE(SUM(case when value > 0 then value end),0) votes_up,
COALESCE(SUM(case when value < 0 then value end),0) votes_down,
COALESCE(SUM(value),0) votes_aggregate
FROM ideas
LEFT JOIN votes ON ideas.id = votes.idea_id
GROUP BY ideas.id
) as t
LEFT JOIN tags_rel ON t.id = tags_rel.idea_id
LEFT JOIN tags ON tags_rel.tag_id = tags.id
WHERE t.published = 1
AND vup IS NOT NULL
GROUP BY t.id
ORDER BY vup DESC

mySQL - Limit the number of rows returned in one side of JOIN statement?

Everyone,
I am just curious if there is a way to do this sort of limiting with a query on a mySQL database:
Here are my tables:
Events
event_id event_title creation_time
Images
image_id src event_id
Comments
event_comment_id event_comment event_id
I would like to fetch events sorted by creation time, and get only 3 images and 3 comments for each event.
Any help, resources, or criticism is welcome. Thank you
Here's one approach. Basically, get the rownumber associated with each group of comments/images and only display up to 3:
SELECT E.*,
MAX(CASE WHEN I.rn = 1 THEN I.Image_Id END) Image1,
MAX(CASE WHEN I.rn = 2 THEN I.Image_Id END) Image2,
MAX(CASE WHEN I.rn = 3 THEN I.Image_Id END) Image3,
MAX(CASE WHEN C.rn = 1 THEN C.event_comment_id END) Comment1,
MAX(CASE WHEN C.rn = 2 THEN C.event_comment_id END) Comment2,
MAX(CASE WHEN C.rn = 3 THEN C.event_comment_id END) Comment3
FROM Events E
LEFT JOIN (SELECT #curRow:=IF(#prevRow = event_id, #curRow + 1, 1) rn,
Image_Id, src, event_id, #prevRow:= event_id
FROM Images
JOIN (SELECT #curRow := 0) r
) I ON E.event_id = I.Event_id
LEFT JOIN (SELECT #curRow2:=IF(#prevRow2 = event_id, #curRow2 + 1, 1) rn,
event_comment_id, event_comment, event_id, #prevRow2:= event_id
FROM Comments
JOIN (SELECT #curRow2 := 0) r
) C ON E.event_id = C.Event_id
GROUP BY E.Event_Id
ORDER BY E.Event_Id, E.creation_time DESC
And here is the SQL Fiddle.

simplify this query

SELECT COUNT( sendbook.id ) AS total, SUM( sendbook.num ) AS num, (
SELECT COUNT( sendbook.id )
FROM sendbook
INNER JOIN clients ON clients.id = sendbook.clientid
WHERE sendbook.issueid = '29'
AND clients.area >1000
AND clients.area <2000
) AS area1000, (
SELECT COUNT( sendbook.id )
FROM sendbook
INNER JOIN clients ON clients.id = sendbook.clientid
WHERE sendbook.issueid = '29'
AND clients.area >2000
AND clients.area <3000
) AS area2000, (
SELECT COUNT( sendbook.id )
FROM sendbook
INNER JOIN clients ON clients.id = sendbook.clientid
WHERE sendbook.issueid = '29'
AND clients.area >3000
AND clients.area <4001
) AS area2000
FROM `sendbook`
WHERE sendbook.issueid = '29'
total num area1000 area2000 area2000
8 438 3 3 2
Do you know a way to simplify this query?
Thinks
you need to use case statement something like this :
SELECT COUNT( sendbook.id ),
(CASE
WHEN clients.area between '1000' and '2000' THEN 1
WHEN clients.area between '2000' and '3000' THEN 2
WHEN clients.area between '3000' and '4000' THEN 3
END) AS myrange FROM mytable
GROUP BY myrange