what is wrong with this UNION ALL mysql query? - mysql

SELECT 'Q' AS TYPE,
q.question AS value,
q.date
FROM questions q
WHERE q.user_id =39
UNION ALL
SELECT 'A' AS TYPE,
q.question AS value,
a.date
FROM answers a,
questions q
WHERE a.question_id = q.id
AND WHERE a.user_id =39
ORDER BY `date` DESC
database design:
questions{id,user_id,question,date}
answers{id,question_id,user_id,answer,date}
error:
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE a . user_id = 39 ORDER BY date DESC

There are two WHERE-clauses in the lower part of the query. You need to literally remove just the last word WHERE. The error description is all you need.

"WHERE" appears twice. Where x = ..... AND ....

Had an extra where a.user_id=39. You only use the keyword WHERE at the beginning of the clause (a.question_id = q.id AND a.user_id = 39)
SELECT
'Q' AS TYPE , q.question AS value, q.date
FROM questions q
WHERE q.user_id =39
UNION ALL
SELECT 'A' AS TYPE , q.question AS value, a.date
FROM answers a,questions q
WHERE a.question_id = q.id
AND
a.user_id =39
ORDER BY `date` DESC

As the error tries to explain: For the second select you only need to put one "WHERE".
SELECT 'A' AS TYPE , q.question AS value, a.date
FROM answers a,questions q
WHERE a.question_id = q.id
AND
a.user_id =39

Related

can't write the correct syntax for the next query

There are 3 entities besides User : Answer, Question and Votes_on_Answers which contains users votes of answers
Answer is associated with Question table by Many-To-One relationship
I need to write query that sums the amount of votes of answer and sort them but I have diffulty with writing the if statement
select a.id, a.question_id, a.user_id,
case
when sum(voa.vote) = null
then 0
else sum(voa.vote)
end as i
from answer as a left join votes_on_answers as voa on a.id = voa.answer_id
where a.question_id = 1
group by a.id order by i desc;
This query returns:
id question_id i
1 1 3
2 1 -2
3 1 null
In this case you could avoid the case .. when and use ifnul()
select a.id
, a.question_id
, sum(ifnull(voa.vote,0)) as i
from answer as a
left join votes_on_answers as voa on a.id = voa.answer_id
where a.question_id = 1
group by a.id
order by i desc;
or using case
select a.id
, a.question_id
, sum(case when voa.vote is null then 0 else voa.vote end)) as i
from answer as a
left join votes_on_answers as voa on a.id = voa.answer_id
where a.question_id = 1
group by a.id
order by i desc;
You might find that a correlated subquery is simpler and faster . . . and you don't have to worry about null values:
select a.id, a.question_id, a.user_id,
(select coalesce(sum(v.votes), 0)
from votes_on_answers voa
where a.id = voa.answer_id
) as i
from answer a
where a.question_id = 1
order by i desc;
For performance you want an index on votes_on_answers(answer_id).
Avoiding the outer group by is a win from the performance perspective. When there are no matches in voa, the count(*) returns 0.

SQL: how to get views count from multiple articles sorted by category?

I use MySQL and I have a code that gets last 6 articles from each category:
select a.*
from article a
where a.created >= coalesce((select a2.created
from article a2
where a2.category = a.category
order by a2.created desc
limit 5, 1
), a.created
);
Now I need also get total views for each article from another table. How to do that? This does not work:
select a.*, Count(view.*) as CountViews
from article a
where a.created >= coalesce((select a2.created
from article a2
where a2.category = a.category
order by a2.created desc
limit 5, 1
), a.created
) left join view on a.id = view.post_id;
Example of printing articles by categories: https://nedvigimostmsk.ru/
Since Gordon appears to be offline right now I'll post my edit here as another answer. This should give you the order by that you want.
select a.*,
(select count(*)
from views v
where a.id = v.post_id
) as num_views
from article a
where a.created >= coalesce((select a2.created
from article a2
where a2.category = a.category
order by a2.created desc
limit 5, 1
), a.created
)
ORDER BY a.created DESC;
I might suggest using a subquery:
select a.*,
(select count(*)
from views v
where a.id = v.post_id
) as num_views
from article a
where a.created >= coalesce((select a2.created
from article a2
where a2.category = a.category
order by a2.created desc
limit 5, 1
), a.created
);
The problem with your query is that you are using COUNT() with no GROUP BY. Either this returns an error (with default setting in the more recent versions of MySQL) or it returns one mysterious row. You can fix this with a GROUP BY, but a correlated subquery often has better performance -- particularly with the right indexes.
Alternative to Gordon, You can also make a join on a nested query that count and group from the views table
select a.*, v.cnt as total_views
from article a
inner join
(
select post_id, count(*) as cnt from views group by post_id
) v on a .id = v.post_id
where a.created >= coalesce((select a2.created
from article a2
where a2.category = a.category
order by a2.created desc
limit 5, 1
), a.created
);
I would try this
... )left join view on a.id = view.post_id
GROUP BY a.*
Also, in your SELECT statement, use this instead of COUNT(view.*) AS CountViews
COUNT(view.post_id) AS CountViews
Generally speaking, it's better to list out the specific columns you want to return rather than just using SELECT a.*

SELECT query IF CONDITION

I have one problem with my SELECT query in my blog page.
I want comment count of each blog when comment status=1.
I am apply following query..
SELECT CONCAT(u.first_name," ",u.last_name) name, r.*,
IF(c.status=1,COUNT(c.id)) as comment
FROM users u
RIGHT JOIN resources r ON u.id = r.created_by
LEFT JOIN comments c ON r.id = c.resource_id
WHERE r.type = 1
AND r.status=1
GROUP BY r.id
ORDER BY r.created_date DESC
LIMIT 0,5
but it giving SYNTAX ERROR..
Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your
SQL syntax; check the manual that corresponds to your MariaDB server version for the right
syntax to use near ') as comment FROM users u RIGHT JOIN resources r ON u.id = r.created_by
LEFT JOI' at line 1
Please tell me where I am wrong.
Thanks
If statement contains three expressions. First, the expression, second the value returned if condition is true and third if condition is false so you are missing the third expression.
Try the below code
SELECT CONCAT(u.first_name," ",u.last_name) name,r.*,IF(c.status=1,COUNT(c.id), 0) as comment
FROM users u RIGHT JOIN resources r ON u.id = r.created_by
LEFT JOIN comments c ON r.id = c.resource_id
WHERE r.type = 1
AND r.status=1
GROUP BY r.id
ORDER BY r.created_date DESC
LIMIT 0,5
Select concat(u.first_name," ",u.last_name) name,r.*,
case when c.status=1 then COUNT(c.id) end as comment
FROM users u RIGHT JOIN resources r ON u.id = r.created_by
LEFT JOIN comments c ON r.id = c.resource_id
WHERE r.type = 1
AND r.status=1
GROUP BY r.id
ORDER BY r.created_date DESC
LIMIT 0,5
https://www.w3schools.com/sql/func_mysql_case.asp
if function requires 3 parameters to be passed to it. IF(expression ,expr_true, expr_false) is how it should be used.
Have a look at https://www.w3resource.com/mysql/control-flow-functions/if-function.php

MySql order by clause not working

In mysql query I use order by, but it is not working.
When I do this
SELECT t.id,t.user_id,t.title,c.comment,d.has_answer,IF(c.id IS NULL, t.date_created, d.recent_date) recent_date,MIN(i.id) image_id
FROM threads t
LEFT JOIN comments c ON c.thread_id = t.id
INNER JOIN (
SELECT thread_id, MAX(date_sent) recent_date, MAX(is_answer) has_answer
FROM comments
GROUP BY thread_id
) d ON c.id IS NULL OR (d.thread_id = c.thread_id AND d.recent_date = c.date_sent)
LEFT JOIN thread_images i ON t.id = i.thread_id
WHERE t.user_id = t.user_id
GROUP BY t.id
ORDER BY d.recent_date DESC
LIMIT 0, 10
It doesn't properly order them. But if I do this:
SELECT *
FROM (
SELECT t.id,t.user_id,t.title,c.comment,d.has_answer,IF(c.id IS NULL, t.date_created, d.recent_date) recent_date,MIN(i.id) image_id
FROM threads t
LEFT JOIN comments c ON c.thread_id = t.id
INNER JOIN (
SELECT thread_id, MAX(date_sent) recent_date, MAX(is_answer) has_answer
FROM comments
GROUP BY thread_id
) d ON c.id IS NULL OR (d.thread_id = c.thread_id AND d.recent_date = c.date_sent)
LEFT JOIN thread_images i ON t.id = i.thread_id
WHERE t.user_id = t.user_id
GROUP BY t.id
LIMIT 0, 10) qwerty
ORDER BY recent_date DESC
Then it does work. Why does the top one not work, and is the second way the best way to fix that?
Thanks
Those two statements are ordering by two different things.
The second statement is ordering by the result of an expression in the SELECT list.
But the first statement specifies ordering by a value of recent_date returned by the inline view d; if you remove "d." from in front of recent_date, then the ORDER BY clause would reference the alias assigned to the expression in the SELECT list, as the second statement does.
Because recent_date is an alias for an expression the SELECT list, these two are equivalent:
ORDER BY recent_date
ORDER BY IF(c.id IS NULL, t.date_created, d.recent_date)
^^
but those are significantly different from:
ORDER BY d.recent_date
^^
Note that the non-standard use of the GROUP BY clause may be masking some values of recent_date which are discarded by the query. This usage of the GROUP BY clause is a MySQL extension to the SQL Standard; most other relational databases would throw an error with this statement. It's possible to get MySQL to throw the same type of error by enabling the ONLY_FULL_GROUP_BY SQL mode.
Q Is the second statement the best way to fix that?
A If that statement guarantees that the resultset returned meets your specification, then it's a workable approach. (One downside is the overhead of the inline view query.)
But I strongly suspect that the second statement is really just masking the problem, not really fixing it.
SELECT t.id,t.user_id,t.title,c.comment,d.has_answer,IF(c.id IS NULL, t.date_created, d.recent_date) recent_date,MIN(i.id) image_id
FROM (threads t
LEFT JOIN comments c ON c.thread_id = t.id
INNER JOIN (
SELECT thread_id, MAX(date_sent) recent_date, MAX(is_answer) has_answer
FROM comments
GROUP BY thread_id
) d ON c.id IS NULL OR (d.thread_id = c.thread_id AND d.recent_date = c.date_sent)
LEFT JOIN thread_images i ON t.id = i.thread_id
WHERE t.user_id = t.user_id
GROUP BY t.id
LIMIT 0, 10) x
ORDER BY d.recent_date DESC

IF within WHERE

I wrote a query with a IF() statement within WHERE clause:
SELECT DISTINCT a.*, u.user_email, u.user_nicename, u.user_login, u.display_name
(
SELECT b.date_recorded
FROM wp_bp_activity as b
WHERE b.type IN ( 'activity_comment','activity_update' )
AND IF(b.type = 'activity_comment', b.item_id, a.id) = a.id
ORDER BY b.item_id desc
limit 0,1
) as drecord
FROM wp_bp_activity as a
LEFT JOIN wp_users as u ON a.user_id = u.ID
WHERE
a.type IN ( 'activity_update' )
order by cast(drecord as datetime) desc
limit 0,20
But it gives error:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT b.date_recorded FROM wp_bp_activity as b WHERE b.' at line 3
What's the correct way of using IF like that?
First thing to change is to add comma after u.display_name. It should help.
You miss a comma after u.display_name ... query will be
SELECT DISTINCT a.*, u.user_email, u.user_nicename, u.user_login, u.display_name,
(
SELECT b.date_recorded
FROM wp_bp_activity as b
WHERE b.type IN ( 'activity_comment','activity_update' )
AND IF(b.type = 'activity_comment', b.item_id, a.id) = a.id
ORDER BY b.item_id desc
limit 0,1
) as drecord
FROM wp_bp_activity as a
LEFT JOIN wp_users as u ON a.user_id = u.ID
WHERE
a.type IN ( 'activity_update' )
order by cast(drecord as datetime) desc
limit 0,20
hope this fix the issue... as I didn't check for other errors.
Do you even need the if ?
((b.type = 'activity_comment' AND b.item_id = a.id) OR (b.type <> 'activity_comment'))
seems to be what you are trying to do
The SQL error like others have said though is the missing comma