MySQL unknown column using subquery - mysql

I receive an error when i execute this query:
SELECT
(SELECT count(cp_projeto_view.id) FROM cp_projeto_view WHERE cp_projeto_view.id_projeto = cp_projeto.id AND cp_projeto_view.id_pessoa = 467 LIMIT 1) AS qtde_visualizacoes
FROM cp_projeto
WHERE qtde_visualizacoes = 0
The error is: #1054 - Unknown column 'qtde_visualizacoes' in 'where clause'
Why qtde_visualizacoes does not exists?
Thank you very much!

You cannot use a column alias in a where clause (unless you use a subquery). MySQL has an extension where you can use having instead:
SELECT (SELECT count(cp_projeto_view.id)
FROM cp_projeto_view
WHERE cp_projeto_view.id_projeto = cp_projeto.id AND cp_projeto_view.id_pessoa = 467
LIMIT 1
) AS qtde_visualizacoes
FROM cp_projeto
HAVING qtde_visualizacoes = 0
EDIT:
The query that you probably want is more like:
select p.*
from cp_projecto p
where not exists (select 1 from cp_projeto_view pv where pv.id_projeto = p.id and pv.id_pessoa = 467)
This will return all cp_projectos that have no matching rows in cp_projeto_view. Your original query would only return rows with a single column of 0s, which doesn't make much sense. If you want the count, then do:
select count(*) as cnt
from cp_projecto p
where not exists (select 1 from cp_projeto_view pv where pv.id_projeto = p.id and pv.id_pessoa = 467)
And, for performance, create an index on cp_projeto_view(projeto, id_pessoa).

Related

MySQL Count as {name} and WHERE {name} = X, Unknown column

I am trying to filter results based on the name assigned on count() and get this:
Unknown column 'total_submissions' in 'where clause'
SELECT SQL_CALC_FOUND_ROWS patient.*,count(patient_data.id) as total_submissions
FROM patient
LEFT JOIN patient_data ON (patient_data.patient_id = patient.id AND patient_data.date_finished IS NOT NULL)
WHERE patient.doc_id = 2 AND total_submissions = 5
GROUP BY patient.id
ORDER BY patient.id DESC
LIMIT 0,40
After more research I did find out about not being able to use a column alias in the WHERE but I am unsure how to execute this query then. I assume it's possible but how would I be able to filter the results based on the count() calculation of the query?
total_submissions is a column alias and the result of an aggregation function. You need to do that check in a havingclause:
SELECT SQL_CALC_FOUND_ROWS p.*, count(pd.id) as total_submissions
FROM patient p LEFT JOIN
patient_data pd
ON pd.patient_id = p.id AND pd.date_finished IS NOT NULL
WHERE p.doc_id = 2
GROUP BY p.id
HAVING total_submissions = 5
ORDER BY p.id DESC
LIMIT 0, 40;
Notes:
Table aliases make the query easier to write and to read.
The condition on doc_id should still be in the WHERE clause.
You can't use column alias in where clause because the precedence in sql evaluation don't let the db engine know the alias name when evaluate the where clause
First is evaluated the FROM clase then the WHERE clause and after the SELECT cluase ..
In your case you have an aggregation function related to yu alias and this can be evaluated only after the group by is performed, pratically at the end of query process
for this reason there is a proper filter based on HAVING that work on the result of the aggreated query
SELECT SQL_CALC_FOUND_ROWS patient.*, count(patient_data.id) as total_submissions
FROM patient
LEFT JOIN patient_data ON (patient_data.patient_id = patient.id AND patient_data.date_finished IS NOT NULL)
WHERE patient.doc_id = 2
GROUP BY patient.id
HAVING total_submissions = 0
ORDER BY patient.id DESC
LIMIT 0,40

mySQL 'where name NOT IN' not working?

I have this statement:
SELECT id, name
FROM players
WHERE this = 1
AND name NOT IN (SELECT name
FROM players_online
WHERE this = 'that')
ORDER BY RAND()
LIMIT 3, 6
All columns are correctly named. No SQL errors occur, it just returns no results.
From what I've read in documentation it should work, but doesn't.
Any idea?
Don't use NOT IN with subqueries. It has the wrong semantics if any value in the subquery is NULL. In that case, the NOT IN never evaluates to TRUE, so no rows are returned at all.
Instead, use NOT EXISTS:
SELECT p.id, p.name
FROM players p
WHERE p.this = 1 AND
NOT EXISTS (SELECT 1
FROM players_online po
WHERE po.name = p.name AND po.this = 'that'
)
ORDER BY RAND()
LIMIT 3, 6;

Custom sub-select requests and where clauses with MySQL

I'm trying to list the content of a table using sub-selects and select only the one that match my WHERE clause:
SELECT DISTINCT `torrentItem` as ti,
(SELECT COUNT(*) FROM votes WHERE `torrentItem` = ti AND `voteType` = 0) AS `badVotes`,
(SELECT COUNT(*) FROM votes WHERE `torrentItem` = ti AND `voteType` = 1) AS `goodVotes`,
(SELECT TIMESTAMPDIFF(WEEK,(SELECT MAX(`date`) FROM votes WHERE `torrentItem` = ti),CURRENT_TIMESTAMP)) AS `weeksSinceLastVote`
FROM `votes`
WHERE (`badVotes` > 1 AND `goodVotes` = 0 AND `weeksSinceLastVote` > 1);
It's not working : MySQL tells me that I can't just use badVotes or goodVotes in the WHERE clause :
Error Code: 1054. Unknown column 'badVotes' in 'where clause'
Can you explain me why ? And how to do it ?
For each row in your table each subquery is executed. Performance nightmare :)
You can rewrite your query as
SELECT `torrentItem` as ti,
SUM(`voteType` = 0) AS `badVotes`,
SUM(`voteType` = 1) AS `goodVotes`,
TIMESTAMPDIFF(WEEK, MAX(`date`), CURRENT_TIMESTAMP) AS `weeksSinceLastVote`
FROM `votes`
GROUP BY ti
HAVING (`badVotes` > 1 AND `goodVotes` = 0 AND `weeksSinceLastVote` > 1);
This will run much, much better than your subqueries.
The reason why you can't use an alias in the where clause is the order in which a query is interpreted.
FROM
WHERE
GROUP BY
HAVING
ORDER BY
SELECT
You can not use the column alias on where clause.
However you can use having clause for the same.
Check more details here http://dev.mysql.com/doc/refman/5.0/en/problems-with-alias.html

How to access outer column values in mysql subquery?

In mysql I have this query
SELECT m.*
FROM members m
RIGHT JOIN (SELECT
IF(`from member_id`=1, `to member_id`, `from member_id`) as other_id, text, `date sent`
FROM message
WHERE ((`from member_id`=1 AND `to member_id`=m.id) OR (`to member_id`=1 OR `from member_id`=m.id))
ORDER BY `date sent` DESC
LIMIT 1
) as t on 1=1
ORDER BY t.`date sent` DESC
and I'm getting this error:
Unknown column 'm.id' in 'where clause'
How can I pass the members column value in the sub query select statement?
I am creating this sub query so it evaluates to 1 row, then I want to attach it to the right of the outer select statement.
Thanks.
You need to SELECT the from member_id/to member_id values in the subquery. Then, you can join the table m on the derived table where you will have access to the values.
) as t on t.`from member_id` = 1 AND t.`to member_id` = m.id
OR t.`to member_id` = 1 OR t.`from member_id` = m.id

MySQL Update with Subquery

I've got an annoying issue with an update query I'm trying to get working... The following statement SHOULD update channels.media_view_count to the result of the subquery (for all channels).
UPDATE channels c
SET c.media_view_count = (
SELECT SUM(t.view_count)
FROM (
SELECT DISTINCT m.viewkey, m.view_count
FROM media m
INNER JOIN participants p ON m.id = p.medium_id
WHERE p.user_id = c.id AND m.is_viewable = 1
AND (p.pending = 0)
) AS t
);
The subquery works fine independently (when specifying an actual id for c.id, like 47778 or whatever), but when I execute this statement, I get:
ERROR 1054 (42S22): Unknown column 'c.id' in 'where clause'
I thought I would be able to access the channels table (aliased as c) from within the subquery? Am I missing something or am I totally wrong here?
Any and all help is appreciated :)
Thanks,
Jeff
UPDATE channels c, (
SELECT t.user_id, SUM(t.view_count) cnt
FROM (
SELECT DISTINCT p.user_id, m.viewkey, m.view_count
FROM media m
INNER JOIN participants p ON m.id = p.medium_id
WHERE m.is_viewable = 1
AND (p.pending = 0)
) AS t GROUP BY t.user_id ) temp
SET c.media_view_count = temp.cnt
WHERE c.id = temp.user_id
Try like this... Did not test it though :) ..
Conceptually, it should work