I have tables like this. but it seems MySQL doesn't count my second join currently. i want to know what i missed for process count of reports for my comment list.
and i want to have average of rates also count of reports
SELECT *, avg(rate.score), count(report.id) FROM `comment`
left join rate on (comment.id = rate.comment_id)
left join report on (comment.id = report.comment_id)
group by comment.id
id text id comment_id score id comment_id type avg(rate.score) count(report.comment_id)
1 good article 1 1 2 1 1 1 4.0000 20
2 bad article NULL NULL NULL NULL NULL NULL NULL 0
good article have 2 reports.
count(report.id) give me wrong value. what's my mistake?
SELECT
*,
avg(rate.score),
(SELECT
count(report.comment_id)
FROM
report
WHERE
comment.id = report.comment_id) AS num_reports
FROM
comment
left join
rate ON (comment.id = rate.comment_id)
group by comment.id
Here's the example:
http://sqlfiddle.com/#!2/cf313/15
You dont need *. Try this
SELECT comment.id, avg(rate.score), count(report.id) FROM `comment`
left join rate on (comment.id = rate.comment_id)
left join report on (comment.id = report.comment_id)
group by comment.id
Related
Basically, there are three tables with the following structure
First table: tournament_questions, having all the questions
id tournament_id question active created_at updated_at
1 5 Text question 1 2018-12-08 20:28:49 NULL
Second table: tournament_options, having all the options
id question_id option correct active created_at updated_at
1 1 1 1 1 2018-12-08 20:29:02 NULL
2 1 26 0 1 2018-12-08 20:29:02 NULL
Third Table: tournament_user_answers, having all the user answers.
id option_id user_id score active created_at updated_at
This table has no data at this time.
I want to achieve all the questions that are not answered by the users and hence the query should return the first question. Here is the query that I tried, but it always returns null
SELECT * FROM tournament_user_answers
INNER JOIN tournament_options ON tournament_user_answers.option_id =
tournament_options.id AND tournament_options.active = 1
LEFT JOIN tournament_questions ON tournament_questions.id =
tournament_options.question_id AND tournament_questions.active = 1
WHERE tournament_questions.tournament_id = 5 AND
tournament_questions.active = 1
AND tournament_questions.id IS NULL AND tournament_user_answers.user_id = 1
LIMIT 1
You start with FROM tournament_user_answers (which is empty) and you do a LEFT JOIN which includes all rows on the left hand (which was empty) and appending on those the data on the right hand if available. empty LEFT JOIN data will be empty.
SELECT
tournament_questions.*
FROM tournament_questions
JOIN tournament_options
ON tournament_options.question_id = tournament_questions.id
AND tournament_options.active = 1
LEFT JOIN tournament_user_answers
ON tournament_user_answers.option_id = tournament_options.id
AND tournament_user_answers.user_id = 1
WHERE
tournament_questions.tournament_id = 5
AND tournament_questions.active = 1
GROUP BY tournament_questions.id
HAVING MAX(tournament_user_answers.id) IS NULL
ORDER BY tournament_questions.id ASC
In this case the left part (questions + options) has data, and the answers are appended if available. By including a MAX(tournament_user_answers.id) IS NULL in your HAVING you get all questions where there is NO answer.
Maybe this would work for your case (reduced version):
SELECT q.id, q.question, ua.id ua_id FROM tournament_questions q
INNER JOIN tournament_options o ON q.id = o.question_id
LEFT JOIN tournament_user_answers ua ON o.id = ua.option_id
GROUP BY q.id
HAVING ua_id IS NULL
So guys, trying to write a query to get the count of statuses where project_id = ? and statuses in 'New' from a couple of tables so let me break it down.
I have these three tables
Case_Status
id case_status
1 New
2 Failed
3. Accepted
Referral
id case_status_id project_id application_id
1 1 1 20
2 2 1 21
Project
id name
1 project1
2 project2
So this is my query
SELECT COUNT(referrals.id) AS count_all, case_statuses.case_status AS counted
FROM "case_statuses" LEFT OUTER JOIN "referrals" ON "referrals"."case_status_id" = "case_statuses"."id"
WHERE "case_statuses"."deleted_at" IS NULL AND (case_statuses.case_status IN ('New') AND referrals.project_id = 1)
GROUP BY case_statuses.case_status;
This is my result
count_all counted
1 New
1 Failed
But I am expecting this result instead
count_all counted
1 New
1 Failed
0 Accepted
Does anyone know what's wrong with my query that isnt showing count for all the case_statuses?
Thanks
Conditions on the second table (in a left join) should be in the on clause:
SELECT COUNT(r.id) AS count_all, cs.case_status AS counted
FROM case_statuses cs LEFT OUTER JOIN
referrals r
ON r.case_status_id = cs.id AND r.project_id = 1
WHERE cs.deleted_at IS NULL AND cs.case_status NOT IN ('New')
GROUP BY cs.case_status;
Otherwise, the WHERE clause turns the outer join into an inner join.
change your query like this
SELECT COUNT(referrals.id) AS count_all, case_statuses.case_status AS counted
FROM "case_statuses" LEFT JOIN "referrals" ON "referrals"."case_status_id" = "case_statuses"."id" AND referrals.project_id = 1
WHERE "case_statuses"."deleted_at" IS NULL AND case_statuses.case_status NOT IN ('New')
GROUP BY case_statuses.case_status;
Given your data and the expected result you just need to loose the WHERE clause.
SELECT COUNT(referrals.id) AS count_all, case_statuses.case_status AS counted
FROM case_statuses
LEFT OUTER JOIN referrals ON referrals.case_status_id = case_statuses.id
GROUP BY case_statuses.case_status;
See this fiddle for details.
I have two tables:
I'm trying to retrieve fields name, quantity and custom_message from table 1 and join the correct associated field value from table 2 - to give me:
name | quantity | custom_message | value
This is my query:
SELECT vxu_4_wpsc_cart_contents.name, vxu_4_wpsc_cart_contents.quantity,
vxu_4_wpsc_cart_contents.custom_message
FROM vxu_4_wpsc_cart_contents
RIGHT JOIN vxu_4_wpsc_submited_form_data
ON vxu_4_wpsc_cart_contents.id = vxu_4_wpsc_submited_form_data.id
WHERE form_id =2
OR form_id =3
which is returning
name | quantity | custom_message
NULL NULL NULL
NULL NULL NULL + 3 more rows of nulls
vxu_4_wpsc_cart_contents:
table 1
vxu_4_wpsc_submited_form_data:
I just don't know where I'm going wrong!
I believe right join should be inner join. Try the following query:
SELECT
vcc.name,
vcc.quantity,
vcc.custom_message,
vfd.value
FROM
vxu_4_wpsc_cart_contents AS vcc
INNER JOIN vxu_4_wpsc_submited_form_data as vfd
ON vcc.purchaseid = vfd.log_id
WHERE
vfd.form_id IN (2,3);
(fyi: your second image link is the same as the first :))
Please consider the following query:
Select all payments of a user and UNION the results with the user's invoices.
SELECT `id`,
`amount` AS `value`,
'PAYMENT' AS `transaction_type`
FROM `payment`
WHERE `user_id` = $user_id
UNION ALL
SELECT `i`.`id`,
(-1) * SUM(`ii`.`unit_price` * `ii`.`quantity`) AS `value`,
'INVOICE' AS `transaction_type`
FROM `invoice` `i`
JOIN `invoiceitem` `ii` ON `ii`.`invoice_id` = `i`.`id`
WHERE `user_id` = $user_id AND `type` = 'invoice'
The problem is that for users that have no payment and no invoice, an unwanted row is returned like this:
id | value | transaction_type
=================================
NULL | 0 | NULL
But for users that have some data, the result is completely expected.
IMPORTANT EDIT
After some more research, I got that the problem should be from the second subquery below:
SELECT i.id,
(-1) * SUM(ii.unit_price * ii.quantity) AS `value`,
'INVOICE' AS `trans_type`
FROM invoice i
JOIN invoiceitem ii ON ii.invoice_id = i.id
WHERE user_id = 4 AND type = 'invoice'
which returns the following:
id | value | transaction_type
=================================
NULL | NULL | INVOICE
Of course the user with user_id = 4 has not yet any invoice. But for another user that has some invoices, the result is OK.
This row is created by the aggregate function SUM. In order to prevent this, use a valid GROUP BY clause, probably GROUP BY user_id
It's impossible to say with any certainty without understanding the complete table descriptions, but based on the update to your question, you need to eliminate rows that have NULL values for the column i.id:
SELECT i.id
, (-1) * SUM(ii.unit_price * ii.quantity) AS `value`
, 'INVOICE' AS `trans_type`
FROM invoice i
JOIN invoiceitem ii
ON ii.invoice_id = i.id
WHERE user_id = 4
AND type = 'invoice'
AND i.id IS NOT NULL
I'm guessing that there is a logical defect in your data model or there might be some other column you should use. I can speculate that this invoice row could be a cancelled order, but it is clear that a row exists where the id column is null, which is why it appears in the result.
To avoid such nulls just use a LEFT JOIN instead of INNER JOIN, so, replace your following sql line:
JOIN `invoiceitem` `ii` ON `ii`.`invoice_id` = `i`.`id`
for this one:
LEFT OUTER JOIN `invoiceitem` `ii` ON `ii`.`invoice_id` = `i`.`id`
I need to join two tables. I only want to show matches where users.private = 0
feeds
id user_id
100 1
101 NULL
102 2
users
id private
1 1
2 0
I have seen many related questions, and the answer is always to move the WHERE condition into ON instead. But if i do this:
SELECT `feeds`.`id`, `feeds`.`user_id` AS `feed_user_id`, `users`.`id` AS `user_id`, `users`.`private`
FROM `feeds`
LEFT JOIN `users` ON `feeds`.`user_id` = `users`.`id`
AND `users`.`private` = 0
This returns
id feed_user_id user_id private
100 1 NULL NULL
101 NULL NULL NULL
102 2 2 0
What I WANT it to do is exclude the first row id 100. (So I guess that is not really a LEFT JOIN -> I want it to LEFT JOIN if the condition is met, otherwise exclude) How can I do this?
You need two separate condition clauses, one on the JOIN and one on the SELECT, like so:
SELECT `feeds`.`id`, `feeds`.`user_id` AS `feed_user_id`, `users`.`id` AS `user_id`, `users`.`private`
FROM `feeds`
LEFT JOIN `users` ON `feeds`.`user_id` = `users`.`id`
WHERE `users`.`private` = 0 OR `feeds`.`user_id' IS NULL
The problem with your current approach is that the join is treating private users as if they don't exist, rather than saying "this person exists and I should exclude this row from the results".