Mysql select count on left join with condition not working - mysql

I need to count number of records on left table, i read other questions and end up with this query but the condition on COUNT is ignored
SELECT a.name, COUNT( f.status <> 'e' ) AS total
FROM album AS a LEFT JOIN photo AS f
ON a.id = f.idalbum
WHERE a.iduser = 4
GROUP BY a.id
is MySQL 5 DB

you cant specify a condition inside COUNT statment.
try this
SELECT a.name, COUNT( f.status ) AS total
FROM album AS a LEFT JOIN photo AS f
ON a.id = f.idalbum
WHERE a.iduser = 4 or f.status <> 'e'
GROUP BY a.id

What if you do:
SELECT a.name, COUNT( f.status ) AS total
FROM album AS a LEFT JOIN photo AS f
ON a.id = f.idalbum
WHERE a.iduser = 4 and f.status != 'e'
GROUP BY a.id

Related

Many select statement from multiple condition

I want to display a data table with a query using many selects and various conditions, I've tried it but the result is that each column content keeps repeating and many duplicates.
I hope someone can help solve my problem
the result of my query :
While the result I want is as follows :
agent
blast
replied
responded
awaiting
no_reply
Harry
Andrian
50
20
10
10
5
James
40
20
15
6
8
Superadmin
100
20
10
10
50
I tried :
SELECT t1.agent,
t2.blast,
t3.replied,
t4.responded,
t5.awaiting,
t6.no_reply
FROM (SELECT realname AS agent
FROM user) AS t1 -- this is for agent,
(SELECT count(*) AS blast
FROM message_thread
right join user
on message_thread.agent_id = user.id
right join message
on message_thread.id = message.message_thread_id
where message.status = 'sent'
group by message_thread.agent_id) AS t2 -- this is for blast,
(select count(*) as replied
from message_thread
right join user
on message_thread.agent_id = user.id
right join message
on message_thread.id = message.message_thread_id
where message.status = 'delivered'
group by message_thread.agent_id) AS t3 -- this is for replied,
(SELECT count(DISTINCT a.id) AS responded
FROM message_thread a
right join user
on a.agent_id = user.id
WHERE
EXISTS(
SELECT 1 FROM message_thread b
right join message e
on b.id = e.message_thread_id
WHERE a.id = b.id
AND e.status = 'sent'
) and exists (
SELECT 1 FROM message_thread c
right join message f
on c.id = f.message_thread_id
WHERE a.id = c.id
AND f.status = ''
)and exists(
SELECT 1 FROM message_thread d
right join message g
on d.id = g.message_thread_id
WHERE a.id = d.id
AND g.status = 'delivered'
)
group by a.agent_id) AS t4 -- this is for responded,
(SELECT count(DISTINCT a.id) AS awaiting
FROM message_thread a
right join user
on a.agent_id = user.id
WHERE
EXISTS(
SELECT 1 FROM message_thread b
right join message e
on b.id = e.message_thread_id
WHERE a.id = b.id
AND e.status = 'sent'
)and not exists (
SELECT 1 FROM message_thread c
right join message f
on c.id = f.message_thread_id
WHERE a.id = c.id
AND f.status = ''
)and exists(
SELECT 1 FROM message_thread d
right join message g
on d.id = g.message_thread_id
WHERE a.id = d.id
AND g.status = 'delivered'
)
group by a.agent_id) AS t5 -- this is for awaiting,
(SELECT count(DISTINCT a.id) AS no_reply
FROM message_thread a
right join user
on a.agent_id = user.id
WHERE not exists(
SELECT 1 FROM message_thread d
right join message g
on d.id = g.message_thread_id
WHERE a.id = d.id
AND g.status = 'delivered'
)
group by a.agent_id) AS t6 -- this is for no_reply

count a specific row on a nested query

I'm trying to count the number of records on a particular field with the query below.
SELECT COUNT(DISTINCT CASE WHEN seen='n' and reciever_id=1 THEN 'varb' ELSE 'novarb' END) AS count ,c.id, c.vmsg, c.sender_id, p.fname, p.lname, p.profile_pix, p.profile_id
FROM chats c LEFT JOIN profile p ON c.sender_id = p.profile_id
WHERE c.reciever_id = 1 AND c.id in (SELECT MAX(c.id) as id FROM chats c
GROUP BY c.sender_id )
But the answer i get only returns it just one record whiles there other hundreds to be displayed
If you use varb and novarb the dictinct count is max 2 if you have 1 mean that you have one condition only
could be you need that count the number of varb entries
SELECT COUNT(
CASE WHEN seen ='n' and reciever_id=1
THEN 'varb'
ELSE NULL
END) AS count ,c.id, c.vmsg, c.sender_id, p.fname, p.lname, p.profile_pix, p.profile_id
FROM chats c
LEFT JOIN profile p ON c.sender_id = p.profile_id
WHERE c.reciever_id = 1 AND c.id in (
SELECT MAX(c.id) as id FROM chats c
GROUP BY c.sender_id )
I usually use SUM() for this purpose. If I understand correctly, you want the number of rows that meet the condition and don't meet the condition:
SELECT SUM( seen = 'n' and reciever_id = 1 ) as varb,
SUM( not (seen = 'n' and reciever_id = 1) ) as novarb,
c.id, c.vmsg, c.sender_id, p.fname, p.lname, p.profile_pix, p.profile_id
FROM chats c JOIN -- I doubt a left join is necessary
profile p
ON c.sender_id = p.profile_id
WHERE c.reciever_id = 1 AND
c.id in (SELECT MAX(c2.id) FROM chats c2 GROUP BY c2.sender_id)

mysql subquery select with field from query

i have a little problem with a subquery in sql.
her the query
SELECT st.title, count(q.id) as question_count, max(a.id) as maxid,
sum(case when a.answer is not null then 1 else 0 end) as answer_count, g.user_id as game_user_id,
a.game_id as a_game_id, a.modified as finished, (select modified as finished from answers a where a.id = g.maxid limit 1) as subquery
FROM games g
left join answers a on(a.game_id = g.id)
left join questions q on(a.question_id = q.id)
left join sessions s on(s.id = q.session_id)
left join sessiontypes st on(st.id = s.sessiontype_id)
WHERE g.user_id = 21
group by g.id
having(question_count = answer_count)
order by finished DESC;
i want that the subquery returns the modified value from answers where the id is the highest grouped by game.
so i tried to select max(id) as maxid... and the use max id in the subquery. where a.id = maxid. nice try, but dont work.
mysql error is this one: Reference 'maxid' not supported (reference to group function)
can anybody give a hint how to solve that?
Join on a subquery which returns the MAX(answers.id) grouped by the answers.game_id.
Then use that maxid to join on the answers table to get the row of the corresponding answers.id.
Not sure, how your result is supposed to look, in your select I removed a.modified AS finished, and replaced it with the modified column of the row with maxid.
SELECT
st.title,
count(q.id) AS question_count,
sum(
CASE
WHEN a.answer IS NOT NULL THEN
1
ELSE
0
END
) AS answer_count,
g.user_id AS game_user_id,
a.maxid,
a.game_id AS a_game_id,
modifiedAnswer.modified AS finished,
FROM
games g
LEFT JOIN (SELECT MAX(answers.id) AS maxid, game_id FROM answers GROUP BY answers.game_id) AS a ON (a.game_id = g.id)
LEFT JOIN answers AS modifiedAnswer ON modifiedAnswer.id = a.maxid
LEFT JOIN questions q ON (a.question_id = q.id)
LEFT JOIN sessions s ON (s.id = q.session_id)
LEFT JOIN sessiontypes st ON (st.id = s.sessiontype_id)
WHERE
g.user_id = 21
GROUP BY
g.id
HAVING
(
question_count = answer_count
)
ORDER BY
finished DESC;

How Do I Count Number of Males and Females

I have the query as follows:
select d.question, b.response, count(b.response)
from sl_flow a
INNER JOIN ul_attempt_responses b on a.question_id = b.question_id and b.type = 1
INNER JOIN us_attempts c on c.id = b.attempt_id
INNER JOIN ss_questions d on d.id = a.question_id
where a.status = 1
and a.ckm_question = 0
and b.response
group by a.question_id, b.response
order by a.question_order asc
The above gives me the questions that I have in the DB which are active and their responses and counts.
However I need a query that will give me number of males and females that answered each of the question. Therefore, I have another query that gives me the number of males and females which is:
SELECT
concat(a.response, 's') as gender,
count(a.response) as count
FROM
ul_attempt_responses a
INNER JOIN us_attempts b ON a.attempt_id = b.id
WHERE
a.question_id = 6 and a.type = 0 AND trim(a.response) != ''
GROUP by a.response;
I am not sure, how to do so. For the gender, the question_id is 6 and type on the a table has to be 0 (the a table is ul_attempt_responses).
This is what I got so far. However, it appears that the results I am getting may not be consistent:
SELECT
gender.question
,coalesce(sum(case final.Response when 'male' then gender.total end),0) as 'Males'
,coalesce(sum(case final.Response when 'female' then gender.total end),0) as 'Females'
FROM
(SELECT
stats . *,
(CASE concat(stats.userid, stats.QuestionID, stats.type)
WHEN #curType THEN #curRow:=coalesce(#curRow, 0) + 1
ELSE #curROw:=1
AND #curType:=concat(stats.userid, stats.QuestionID, stats.type)
END) + 1 AS rank
FROM
(SELECT
d.question as Question,
a.user_id AS UserID,
c.question_id AS QuestionID,
c.type as Type,
c.response AS Response,
a.campaign_id as campaign_id
FROM
us_attempts a
INNER JOIN ul_attempt_responses c ON a.id = c.attempt_id
RIGHT OUTER JOIN ss_profile_questions d ON c.question_id = d.id AND c.type = 0
LEFT OUTER JOIN sl_profile_flow f ON c.question_id = f.profile_question_id
RIGHT OUTER JOIN us_users g ON g.id = a.user_id
WHERE
f.status = 1
ORDER BY a.user_id , c.question_id , c.type , a.id desc) stats) final
INNER JOIN
(select b.user_id, c.question as question, count(1) as total
from ul_attempt_responses a
INNER JOIN us_attempts b on a.attempt_id = b.id
INNER JOIN ss_questions c on a.question_id = c.id and a.type = 1
group by b.user_id, c.id) gender on final.UserID = gender.user_id
where
final.rank = 2 and final.QuestionID = 6 and final.campaign_id = 3
group by gender.question;
Is there a way I can reduce the above query, or is there a better optimized way?
You could use a combination of sum and case/if to get the counts. Given your full table structures are not clear, I am assuming you have a table (or an SQL that can produce a set of rows) with the following fields:
response_id
question_id
response
Then an SQL such as
select question_id
, response
, sum(if(gender='M',1,0)) as males
, sum(if(gender='F',1,0)) as females
from (select q.question_id
, q.response
, g.response as gender from answers as q
left join answers as g on q.response_id=g.response_id and g.question_id=6
where q.question_id!=6) as t
group by question_id, response
would give you a result of the form
question_id,response,males,females
1,A,1,2
1,B,1,0
2,A,0,1
2,B,1,1
2,C,1,0
To explain the code, the sub query produces a set of rows for each response with the question mapped with the gender question's response. In the main select statement the if statement produces a 1 for the specific gender in the proper column and summing them up gives you how many of that specific gender responded to that question.
EDIT
As suggested by #Strawberry, the shorter version would be
select q.question_id
, q.response_id
, sum(g.response='M') as males
, sum(g.response='F') as females
from answers as q
left
join test as g
on q.response_id = g.response_id
and g.question_id = 6
where q.question_id != 6
group
by q.question_id
, q.response

SQL JOIN vars not working

I'm trying to select variables from 3 tables using 2 left joins.
SELECT a.username, a.id, COUNT(c.featured)
FROM user a
LEFT JOIN board b
ON a.id = b.user_id
LEFT JOIN pins c
ON a.id = c.user_id
WHERE c.featured='yes'
GROUP BY b.board_name
ORDER BY COUNT(c.featured) ASC
LIMIT 3
This should get the 3 highest scoring boards from the database and arrange them according to how many times they have been featured in ascending order. I'm using this to echo:
".$info['b.board_name']."
However nothing is showing
I'm not sure if you want b.boardname or a.username, a.id in your SELECT, but you have to do the GROUP BY accordingly:
Try doing:
SELECT a.username, a.id, COUNT(c.featured)
FROM user a
LEFT JOIN board b ON a.id = b.user_id
LEFT JOIN pins c ON a.id = c.user_id
WHERE c.featured = 'yes'
GROUP BY a.username, a.id
ORDER BY COUNT(c.featured) DESC LIMIT 3
OR
SELECT b.board_name, COUNT(c.featured)
FROM user a
LEFT JOIN board b ON a.id = b.user_id
LEFT JOIN pins c ON a.id = c.user_id
WHERE c.featured = 'yes'
GROUP BY b.board_name
ORDER BY COUNT(c.featured) DESC LIMIT 3