I have the following SQL query which returns 2 results which are the same only different by a where clause.
I would like to have them combined and group them under the user names. At the moment the two results are displayed but the results are not fully combined and the users are shown twice because of the two select statements.
How can I combine the two to create a single result.
The SQL query is as follows
SELECT
COUNT (asings.user_id),
post_status.status_id as status_id,
users.name,
users.id as user_id
from asigns
LEFT JOIN
post_status on asigns.post_id = post_status.post_id
RIGHT JOIN
users on asigns.user_id = users.id
WHERE
post_status.status_id = 2
GROUP BY users.id
UNION
SELECT
COUNT(asigns.user_id),
post_status.status_id as status_id,
users.name,
users.id from asigns
LEFT JOIN
post_status on asigns.post_id = post_status.post_id
RIGHT JOIN
users on asigns.user_id = users.id
WHERE
post_status.status_id = 3
GROUP BY users.id
See in this photo the usernames are appearing twice, what I want is to join the two username, and move count as two different columns depending on the status_id
How can I solve this. Thanks
You should use a single query with conditional aggregation:
SELECT
SUM(ps.status_id = 2) AS cnt_2,
SUM(ps.status_id = 3) AS cnt_3,
u.name,
u.id as user_id
FROM users u
LEFT JOIN assigns a ON a.user_id = u.id
LEFT JOIN post_status ps ON a.post_id = ps.post_id
GROUP BY u.id;
Use SELECT distinct for the union:
SELECT distinct * FROM ([FIRST SELECT] UNION [SECOND SELECT])
Or GROUP BY username
SELECT * FROM ([FIRST SELECT] UNION [SECOND SELECT]) GROUP BY username
BUT I suggest to review your both selects, if it differs just in the where clause so use where clause with the operator OR and you handle it just by one SELECT
Although your are using a LEFT and a RIGHT join and implicitly an INNER join between users and asigns, the WHERE clause transforms all the joins to INNER joins, because you are picking only the matching rows from post_status.
So, you only need INNER joins and conditional aggregation:
SELECT COALESCE(SUM(ps.status_id = 2), 0) counter_2,
COALESCE(SUM(ps.status_id = 3), 0) counter_3,
u.name,
u.id AS user_id
FROM users u
INNER JOIN asigns a ON a.user_id = u.id
INNER JOIN post_status ps ON ps.post_id = a.post_id
WHERE ps.status_id IN (2, 3)
GROUP BY u.id;
Related
I'm trying to select results from two different unrelated tables, showcase and questions to appear in a feed. They should be ordered by the common column hotness which is a float value.
SELECT s.id,s.date,s.title,s.views,s.image,s.hidpi,s.width,s.description,u.display_name,u.avatar
FROM showcase AS s
INNER JOIN users AS u ON s.user_id = u.id
UNION
SELECT q.id,q.date,q.title,q.views,q.text,u.display_name,u.avatar,0,0,0
FROM questions AS q
INNER JOIN users AS u ON q.user_id = u.id
ORDER BY hotness DESC
LIMIT 10
I've tried UNION, but I have no idea how I should be using it here and get this error unknown column hotness
You need to select the value in order for the ORDER BY to recognize it:
SELECT s.id,s.date,s.title,s.views,s.image,s.hidpi,s.width,s.description,u.display_name,u.avatar, s.hotness
FROM showcase AS s
INNER JOIN users AS u ON s.user_id = u.id
UNION ALL
SELECT q.id,q.date,q.title,q.views,q.text,u.display_name,u.avatar,0,0,0, q.hotness
FROM questions AS q
INNER JOIN users AS u ON q.user_id = u.id
ORDER BY hotness DESC;
Note that I also changed the UNION to UNION ALL. Unless you intend to remove duplicates, there is no reason to incur the extra processing for doing that.
You can try this query:
SELECT r.* FROM (
SELECT s.id,s.date,s.title,s.views,s.image,s.hidpi,s.width,s.description,u.display_name,u.avatar, s.hotness
FROM showcase AS s
INNER JOIN users AS u ON s.user_id = u.id
UNION
SELECT q.id,q.date,q.title,q.views,q.text,u.display_name,u.avatar,0,0,0, q.hotness
FROM questions AS q
INNER JOIN users AS u ON q.user_id = u.id
) as r
ORDER BY r.hotness DESC
LIMIT 10
You need to merge Union result in subquery to apply Order by on the result. I also added hotness in select clause, please check I take field from good table.
the MYSQL query below combines a number of tables. However, as you can see, I would like to add a LEFT JOIN at the end on the receipt table. The query returns an error when I add the LEFT JOIN. Anybody know the best way to LEFT JOIN the receipt table to the rest of the query. Sorry if this is a newbie question. Thanks !!
SELECT user_name, expense_category, merchant_name, expense_cost, expense_date, expense_status, receipt_image, expense_comment
FROM users, expenses, merchants, receipts
WHERE ".$adminId." = expenses.admin_id
AND expenses.user_id = users.user_id
AND expenses.merchant_id = merchants.merchant_id
AND LEFT JOIN (receipts)
ON expenses.receipt_id = receipts.receipt_id
Here is a clean approach of doing it, note that I have added alias for the tables for better readability so you may use the alias name in the select statement to fetch the column from the proper table.
SELECT
u.user_name,
ex.expense_category,
mer.merchant_name,
ex.expense_cost,
ex.expense_date,
ex.expense_status,
re.receipt_image,
ex.expense_comment
FROM users u
JOIN expenses ex on ex.user_id = u.user_id
JOIN merchants mer on mer.merchant_id = ex.merchant_id
LEFT JOIN receipts re on re.receipt_id = ex.receipt_id
where
ex.admin_id = '$adminId'
Try this,
SELECT user_name, expense_category, merchant_name, expense_cost, expense_date, expense_status, receipt_image, expense_comment
FROM users, expenses, merchants, receipts
LEFT JOIN receipts ON expenses.receipt_id = receipts.receipt_id
WHERE ".$adminId." = expenses.admin_id
AND expenses.user_id = users.user_id
AND expenses.merchant_id = merchants.merchant_id
Use join clauses instead of where clause. I.e.
SELECT user_name, expense_category, merchant_name, expense_cost, expense_date, expense_status, receipt_image, expense_comment
FROM users
INNER JOIN expenses on users.user_id = expenses.expenses_id
INNER JOIN merchants on merchants.merchant_id = expenses.merchant_id
LEFT JOIN (receipts)
ON expenses.receipt_id = receipts.receipt_id
WHERE ".$adminId." = expenses.admin_id
Note that any columns from the receipts will be NULL in the select statement whenever there's no matching record.
I have three queries gives me result individually correct but my requirement is i need all result in single query only so how should i proceed?
select * from user_post_like
inner join user_post on user_post_like.postID = user_post.postID
inner join Users on Users.userID=user_post_like.userID
where (user_post.poster='$uid' AND user_post_like.userID!='$uid')
ORDER BY likeID DESC;
select * from user_post_comment
inner join user_post on user_post_comment.postID = user_post.postID
inner join Users on Users.userID=user_post_comment.commenter
where (user_post.poster='$uid' AND user_post_comment.commenter!='$uid')
ORDER BY commentID DESC;
select * from user_post_share
inner join user_post on user_post_share.postID = user_post.postID
inner join Users on Users.userID=user_post_share.Share_user_id
where (user_post.poster='$uid' AND user_post_share.Share_user_id!='$uid')
ORDER BY shareID DESC;
Since you're joining the tables anyway, you can put columns from all in your select - and keep your statement readable. If you have duplicate column names (from different tables) you may need to aggregate them with functions and group by.
SELECT s.*, p.*, u.*
FROM user_post_share s
INNER JOIN user_post p ON s.postID = p.postID
INNER JOIN Users u ON u.userID = p.poster
WHERE (p.poster='$uid' AND s.Share_user_id != '$uid')
ORDER BY shareID DESC
try sumthing like this
select * from user_post_like,user_post_comment,user_post_share <inner joins> <where conditions>
I have to tables: USERS and DATA. Every user from USERS can have one, multiple rows on DATA but also any.
I would like to select also the users from USERS without correspondence on DATA but the following query omit them. How should I modify it?
SELECT USERS.id,
USERS.email,
USERS.active,
USERS.last_alert,
DATA.active,
DATA.active_from
FROM USERS
JOIN DATA
WHERE DATA.id_user = USERS.id
AND DATA.active = 1
ORDER BY USERS.id ASC
DATA.id_user contains the USERS.id.
You should use LEFT JOIN instead of INNER JOIN
SELECT
USERS.id,
USERS.email,
USERS.active,
USERS.last_alert,
DATA.active,
DATA.active_from
FROM USERS
LEFT JOIN DATA ON (
DATA.id_user = USERS.id AND DATA.active = 1
)
ORDER BY USERS.id ASC
Do Outer Join
SELECT USERS.id,
USERS.email,
USERS.active,
USERS.last_alert,
DATA.active,
DATA.active_from
FROM DATA
LEFT OUTER JOIN USERS
WHERE DATA.id_user = USERS.id
AND DATA.active = 1
ORDER BY USERS.id ASC
Rewrite it as a LEFT JOIN should include those rows, but not available values will become NULL then
SELECT USERS.id,
USERS.email,
USERS.active,
USERS.last_alert,
DATA.active,
DATA.active_from
FROM USERS
LEFT JOIN DATA ON USERS.id = DATA.id_user AND DATA.active = 1
ORDER BY USERS.id ASC
I have following tables
questions -> id, question_data, user_id
users -> id, fname, lname
question_connect-> id, question_id, user_id
My initial query was as follows
select questions.id, questions.question_data, users.id, users.fname from questions, users where questions.user_id = users.id limit 30
But over here, i want count of users on that question, so i tried following query
select questions.id, questions.question_data, users.id, users.fname, count(questions_connect.id) from questions, users LEFT JOIN questions_connect ON `questions`.`id` = `questions_connect`.`question_id` where questions.user_id = users.id group by `questions_connect`.`id` limit 30
this shows error
Unknown column 'questions.id' in 'on clause'
SO can we make 1 call with natural join and left join and if yes, where i am going wrong..?
Using an explicit join should sort you out:
select questions.id, questions.question_data, users.id, users.fname, count(questions_connect.id)
from questions
join users on questions.user_id = users.id
left join questions_connect on `questions`.`id` = `questions_connect`.`question_id`
group by `questions_connect`.`id`
limit 30
You're better off specifying all your joins explicitly, try to forget that implicit joins exist.
I believe you don't need to put the quotes on the joins
ON questions.id = questions_connect.question_id