Can't Count results from Joined Table mySQL - mysql

i followed 3 others SO answers, and they say it works.. but here not... here is my problem, i have this QUERY:
SELECT
q.*
FROM relacionamento AS r
INNER JOIN questoes AS q ON r.idquestao = q.id
WHERE tabela = 'disciplina'
GROUP BY q.id
This is there result of query:
Until here, it was perfect.. now i need know how much rows returned... i changed the query to this:
SELECT
COUNT(q.*)
FROM relacionamento AS r
INNER JOIN questoes AS q ON r.idquestao = q.id
WHERE tabela = 'disciplina'
GROUP BY q.id
And got this error:
Why i cant count how much rows did i get?
UPDATE:
I did try do this query also:
SELECT
COUNT(*)
FROM relacionamento AS r
INNER JOIN questoes AS q ON r.idquestao = q.id
WHERE tabela = 'disciplina'
GROUP BY q.id
And get this as result:

You can change it like this:
SELECT COUNT(*) FROM (
SELECT
q.*
FROM relacionamento AS r
INNER JOIN questoes AS q ON r.idquestao = q.id
WHERE tabela = 'disciplina'
GROUP BY q.id
)

Your query is probably better written as:
SELECT q.*
FROM questoes q
WHERE EXISTS (SELECT 1
FROM relacionamento r
WHERE r.idquestao = q.id AND r.tabela = 'disciplina'
);
This should be more efficient than your query, if you have an index on relacionamento(idquestao, tablea) (which you would want anyway for the join). And, it doesn't use select * with group by, which just generally looks wrong.
Then, to get the count, you can just do count(*):
SELECT COUNT(*)
FROM questoes q
WHERE EXISTS (SELECT 1
FROM relacionamento r
WHERE r.idquestao = q.id AND r.tabela = 'disciplina'
);

Related

How to reduce JOINs in subquery?

Here is my current query:
SELECT q.type,
q.author_id author,
q.deleted,
q.deleter_id,
COUNT(DISTINCT a.id) answers_num,
COUNT(DISTINCT v.id) votes_num,
FROM qanda q
LEFT JOIN qanda a ON q.id = a.related
LEFT JOIN votes v on q.id = v.post_id
WHERE q.id = ?
It works well. Just I need to add one more thing (which returns a boolean by EXISTS) in the SELECT statement. This:
EXISTS (SELECT a.id, sum(vot.value) total_votes
FROM qanda q
LEFT JOIN qanda a on q.id = a.related
LEFT JOIN votes vot ON a.id = vot.post_id
WHERE q.type = 0 -- this is a question
AND a.related = 1315 -- getting answers
GROUP BY a.id
HAVING total_votes
ORDER BY total_votes DESC
LIMIT1
) as HasAUpvotedAnswer
Ok, it works well too. But I'm worried about the performance. As you can see, the JOINs of those two queries above (which will be combined finally) are similar. How can make them more optimal?
In other word, how can I combine those two above queries in the most optimal case?
Looking to your code could be that y can use a single query using conditional for sum
SELECT q.type,
q.author_id author,
q.deleted,
q.deleter_id,
COUNT(DISTINCT a.id) answers_num,
COUNT(DISTINCT v.id) votes_num,
IF (SUM(
CASE WHEN q.type = 0 AND a.related = 1315
THEN v.value else 0 END) > 0,1,0)
HasAUpvotedAnswer
FROM qanda q
LEFT JOIN qanda a ON q.id = a.related
LEFT JOIN votes v on q.id = v.post_id
WHERE q.id = ?

Mysql can't get data of my parent in a subquery

I've to do a query where the join can access to the data of is parent.
I had this :
SELECT *
FROM tbl_quart q
INNER JOIN tbl_poste_horaire ph ON ph.tbl_quart_id = q.id
INNER JOIN tbl_poste_horaire_caserne phc ON phc.tbl_poste_horaire_id = ph.id
INNER JOIN (
SELECT DISTINCT q1.id,
IF(q1.heureDebut>CURTIME(),ADDTIME(q1.heureDebut,'24:00:00'),
IF(q1.heureFin<CURTIME(),ADDTIME(q1.heureDebut,'48:00:00'),q1.heureDebut)) AS heureTri
FROM tbl_poste_horaire_caserne phc1
INNER JOIN tbl_poste_horaire ph1 ON ph1.id = phc1.tbl_poste_horaire_id
INNER JOIN tbl_quart q1 ON q1.id = ph1.tbl_quart_id
WHERE phc1.tbl_caserne_id = phc.tbl_caserne_id
ORDER BY phc1.tbl_caserne_id, heureTri
LIMIT 2
) AS quartValide ON quartValide.id = q.id
WHERE phc.tbl_caserne_id IN (1,9)
but this request give me that:
Error Code: 1054
Unknown column 'phc.tbl_caserne_id' in 'where clause'
the error is for this line :
WHERE phc1.tbl_caserne_id = phc.tbl_caserne_id
I had also try this :
SELECT *
FROM tbl_quart q
INNER JOIN tbl_poste_horaire ph ON ph.tbl_quart_id = q.id
INNER JOIN tbl_poste_horaire_caserne phc ON phc.tbl_poste_horaire_id = ph.id
WHERE phc.tbl_caserne_id IN (1,9) AND q.id IN ( SELECT DISTINCT q1.id,
IF(q1.heureDebut>CURTIME(),ADDTIME(q1.heureDebut,'24:00:00'),
IF(q1.heureFin<CURTIME(),ADDTIME(q1.heureDebut,'48:00:00'),q1.heureDebut)) AS heureTri
FROM tbl_poste_horaire_caserne phc1
INNER JOIN tbl_poste_horaire ph1 ON ph1.id = phc1.tbl_poste_horaire_id
INNER JOIN tbl_quart q1 ON q1.id = ph1.tbl_quart_id
WHERE phc1.tbl_caserne_id = phc.tbl_caserne_id
ORDER BY phc1.tbl_caserne_id, heureTri
LIMIT 2
)
And i had an error too:
Error Code: 1235
This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
Thanks you for your help :)
Try this way:
SELECT *
FROM tbl_quart q
INNER JOIN tbl_poste_horaire ph ON ph.tbl_quart_id = q.id
INNER JOIN tbl_poste_horaire_caserne phc ON phc.tbl_poste_horaire_id = ph.id
INNER JOIN (
SELECT DISTINCT q1.id,
phc1.tbl_caserne_id
IF(q1.heureDebut>CURTIME(),ADDTIME(q1.heureDebut,'24:00:00'),
IF(q1.heureFin<CURTIME(),ADDTIME(q1.heureDebut,'48:00:00'),q1.heureDebut)) AS heureTri
FROM tbl_poste_horaire_caserne phc1
INNER JOIN tbl_poste_horaire ph1 ON ph1.id = phc1.tbl_poste_horaire_id
INNER JOIN tbl_quart q1 ON q1.id = ph1.tbl_quart_id
ORDER BY phc1.tbl_caserne_id, heureTri
LIMIT 2
) AS quartValide
ON quartValide.id = q.id AND quartValide.tbl_caserne_id = phc.tbl_caserne_id
WHERE phc.tbl_caserne_id IN (1,9)
but it would be better to refactor this query... give me a minute, I think we can simplify it.
it looks like you overcomplecated the query a little. Try this one and tell me what is wrong with result?
SELECT DISTINCT q.*,
ph.*,
phc.*,
IF(q.heureDebut>CURTIME(),ADDTIME(q.heureDebut,'24:00:00'),
IF(q.heureFin<CURTIME(),ADDTIME(q.heureDebut,'48:00:00'),q.heureDebut)) AS heureTri
FROM tbl_poste_horaire_caserne phc
INNER JOIN tbl_poste_horaire ph
ON ph.id = phc.tbl_poste_horaire_id
INNER JOIN tbl_quart q
ON q.id = ph.tbl_quart_id
WHERE phc.tbl_caserne_id IN (1,9)
ORDER BY phc.tbl_caserne_id, heureTri
LIMIT 2

Mysql - LEFT JOIN - get first entry

I have this structure in MySql
I am trying to get:
FIRST post, from LAST topic WHERE category is 'News'
In this example it is row from post where id = 2 as marked on image
So far I got this query:
SELECT *
FROM forum_post AS p
LEFT JOIN forum_topic AS t ON p.topic_id = t.id
LEFT JOIN forum_category AS c ON t.category_id = c.id
WHERE c.title = 'News' AND t.id = MAX(t.id)
ORDER BY p.id ASC LIMIT 1
EDIT:
Dirty solution:
SELECT * FROM forum_post
WHERE topic_id = (SELECT MAX(id) FROM forum_topic WHERE category_id = 1)
ORDER BY id ASC LIMIT 1
You can still use a joined query instead of a subquery to get the first post from last topic of your category,note the subquery in join will run only once to get the result set and in your case subquery will run for each iteration
SELECT * FROM
forum_post AS p
JOIN
(SELECT
t.id
FROM
forum_topic AS t
JOIN forum_category AS c
ON t.category_id = c.id
WHERE c.title = 'News'
ORDER BY t.id DESC
LIMIT 1) t
ON p.topic_id = t.id
ORDER BY p.id ASC
LIMIT 1
select fp.* from forum_post fp,
(select min(fp.id) from forum_post fp where topic_id in
(select max(ft.id) from forum_topic ft inner join forum_category fc
on fc.id = ft.category_id where fc.title = 'News'))T
where fp.id = T.id
[In case there are no forum_posts, no row will be returned]
Edit:
Updated [Although I haven't tried executing it]
I haven't test it, but it shoud be something like this:
SELECT fm.remply
FROM forum_topic ft
JOIN forum_category fc
ON ft.category_id = fc.category_id
AND fc.title = 'News'
JOIN forum_post fm
ON ft.id = fm.topic_id
ORDER BY ft.id DESC
,fm.id DESC
LIMIT 1

Gathering multiple fields

$q = "SELECT s.id, s.title, s.description,
(SELECT COUNT(*) FROM ".FORUM_THREADS." t WHERE t.cat_id = s.id) AS topics,
(SELECT COUNT(*) FROM ".FORUM_REPLIES." r INNER JOIN ".FORUM_THREADS." t ON r.thread_id = t.id
WHERE t.cat_id = s.id) AS replies,
(SELECT r.date FROM ".FORUM_REPLIES." r INNER JOIN ".FORUM_THREADS." t ON r.thread_id = t.id
WHERE t.cat_id = s.id ORDER BY r.date DESC LIMIT 1) AS last_post
FROM ".FORUM_SUBCATEGORIES." s WHERE s.parent = '$catid' AND s.status = '0' ORDER BY s.id";
I am attempting to select more than one field on the following part of the query
(SELECT r.date FROM ".FORUM_REPLIES." r INNER JOIN ".FORUM_THREADS." t ON r.thread_id = t.id
INNER JOIN ".TBL_USERS." u ON u.id = r.author WHERE t.cat_id = s.id ORDER BY r.date DESC LIMIT 1) AS last_post
Along with r.date, I want to select u.username and r.author.
How can I go about doing this?
Thanks!
Just add them to the SELECT:
(SELECT r.date, r.author, u.username FROM ".FORUM_REPLIES." r INNER JOIN ".FORUM_THREADS." t ON r.thread_id = t.id
INNER JOIN ".TBL_USERS." u ON u.id = r.author WHERE t.cat_id = s.id ORDER BY r.date DESC LIMIT 1) AS last_post
UPDATED after comment from OP:
You need to do 3 separate selects OR (depending on your data model) change the query so that the last_post query ends up after/in the FROM clause (there it can have as many columns as you want)...
Luke, you have a central select statement which uses nested select statements for getting the count. You can't depend on the nested select statements to count as the inner join, so you're going to have to add them to the central select statement instead.
In other words, join ".FORUM_REPLIES." and "u" (not sure what that's supposed to represent) with ".FORUM_SUBCATEGORIES.". I'd write the query for you, but I don't know how to link subcategories with replies and subcategories with u.

mysql: multiple join problem

Im trying to select a table with multiple joins, one for the number of comments using COUNT and one to select the total vote value using SUM, the problem is that the two joins affect each other, instead of showing:
3 votes 2 comments
I get 3 * 2 = 6 votes and 2 * 3 comments
This is the query I'm using:
SELECT t.*, COUNT(c.id) as comments, COALESCE(SUM(v.vote), 0) as votes
FROM (topics t)
LEFT JOIN comments c ON c.topic_id = t.id
LEFT JOIN votes v ON v.topic_id = t.id
WHERE t.id = 9
What you're doing is an SQL antipattern that I call Goldberg Machine. Why make the problem so much harder by forcing it to be done in a single SQL query?
Here is how I would really solve this problem:
SELECT t.*, COUNT(c.id) as comments
FROM topics t
LEFT JOIN comments c ON c.topic_id = t.id
WHERE t.id = 9;
SELECT t.*, SUM(v.vote) as votes
FROM topics t
LEFT JOIN votes v ON v.topic_id = t.id
WHERE t.id = 9;
As you have found, combining these two into one query results in a Cartesian product. There may be clever and subtle ways to force it to give you the correct answer in one query, but what happens when you need a third statistic? It's much simpler to do it in two queries.
SELECT t.*, COUNT(c.id) as comments, COALESCE(SUM(v.vote), 0) as votes
FROM (topics t)
LEFT JOIN comments c ON c.topic_id = t.id
LEFT JOIN votes v ON v.topic_id = t.id
WHERE t.id = 9
GROUP BY t.id
or perhaps
SELECT `topics`.*,
(
SELECT COUNT(*)
FROM `comments`
WHERE `topic_id` = `topics`.`id`
) AS `num_comments`,
(
SELECT IFNULL(SUM(`vote`), 0)
FROM `votes`
WHERE `topic_id` = `topics`.`id`
) AS `vote_total`
FROM `topics`
WHERE `id` = 9
SELECT t.*, COUNT(DISTINCT c.id) as comments, COALESCE(SUM(v.vote), 0) as votes
FROM (topics t)
LEFT JOIN comments c ON c.topic_id = t.id
LEFT JOIN votes v ON v.topic_id = t.id
WHERE t.id = 9