I have dialogs and messages. The goal is to select dialogs and their count of unreaded messages. Table messages has unread field to detect it.
I've tried this
SELECT *, count(unread) as nums
FROM dialogs JOIN messages ON dialogs.id=messages.dialog_id
GROUP BY dialogs.id
HAVING count(unread) <> 0
but always get total count of messages
If "unread" is, as you state, a count of unread messages, then it always has a value, even if zero, and is always included in COUNT(unread).
Try inserting a WHERE messages.unread != 0
If you say that the table messages have a column unread, then I don't get why you should count that column, you probably need to sum those values (assuming that there can be more than one record with the same dialog_id on that table). So, I would write your query like this:
SELECT *
FROM dialogs D
INNER JOIN (SELECT dialog_id, COUNT(*) AS nums
FROM messages
WHERE unread = 1
GROUP BY dialog_id) M
ON D.id = M.dialog_id
WHERE M.nums > 0
Oh!!! Count by messages.id.
Try this:
SELECT *, count(messages.id) as nums FROM dialogs
JOIN messages ON dialogs.id=messages.dialog_id
WHERE messages.unread = 1
GROUP BY dialogs.id
HAVING nums <> 0
An Enum type for messages.unread might need to have it quoted:
SELECT *, count(messages.id) as nums FROM dialogs
JOIN messages ON dialogs.id=messages.dialog_id
WHERE messages.unread = '1'
GROUP BY dialogs.id
HAVING nums <> 0
I'm not sure why you'd create a enum('0','1') though....
Related
I am trying to query a table that has a composite key made up of two integers. The relationship is
What I am trying to get as a result is for every conversation that has been started, I want the MAX(threadNum) from the messages table. Currently the query is
SELECT c.conversation_id
FROM conversation as c
INNER JOIN (
SELECT MAX(threadNum), user_from, user_to, message, dateTime, deleted,replied
FROM messages
GROUP BY conversation_id
) as m ON c.conversation_id = m.conversation_Id
WHERE (m.user_to ='$userId' OR m.user_from ='$userId') AND m.deleted = 0
The results that I am expecting for the conversation_Id and the threadNum would be :
35 5
34 4
33 55
one result for every conversation_Id and only the largest threadNum result. Currently I am getting a m.converation_Id is an unknown column. What is wrong with the query structure? And more importantly is there an easier way to do what I am attempting to do?
It looks like you want one row per conversation, along with the latest message in the conversation (that is, the message that has the greatest thread_id).
If so, that's a top-1-per-group problem. You can solve it by filtering with a correlated subquery:
select c.*, m.*
from conversation c
inner join messages m on m.conversation_id = c.conversation_id
where m.thread_num = (
select max(m1.thread_num)
from messages m1
where
m1.conversation_id = m.conversation_id
and m.deleted = 0
and :user_id in (m.user_from, m.user_to)
)
:user_id represents the query parameter for your query (you should use a parameterized query instead of munging the variable into the query string).
Alternatively, if you are running MySQL 8.0, you can use row_number():
select *
from (
select
c.*,
m.*,
row_number() over(partition by c.conversation order by m.thread_num desc) rn
from conversation c
inner join messages m on m.conversation_id = c.conversation_id
where m.deleted = 0 and :user_id in (m.user_from, m.user_to)
) t
where rn = 1
I am new to SQL. I am developing a chat application to get chat conversations like in Facebook. I have written the following query:
select m.toid, m.fmid, m.message, m.seen
from messages m
where ((toid = 5 or fmid = 5))
and not exists (select 1 from messages m2
where greatest (m2.toid, m2.fmid) = reatest(m.toid,m.fmid)
and least (m2.toid, m2.fmid) = least(m.toid,m.fmid)
and m2.message_id > m.message_id )
order by message_id desc
Above query returns as shown below.
Explanation from picture: the last message between 5 and 4 is fghhgj and the message is not seen. Now I want to get number of messages which are not seen between 5 and 4.
I mean I want to get count of seen where seen=0.
In Brief:
Message table contains column called seen. If message is not seen, its value is 0. Now I want to get how many messages are not seen for every conversation.
To count the # of rows where seen is equal to 0 in your result set, put your query inside of a derived table and use select count(*) with where seen = 0
select count(*) from (
select m.toid,m.fmid,m.message,m.seen from messages m
where (toid = 5 or fmid = 5)
and not exists (select 1 from messages m2 where
greatest(m2.toid,m2.fmid) = greatest(m.toid,m.fmid) and
least(m2.toid,m2.fmid) = least(m.toid,m.fmid) and m2.message_id > m.message_id )
) t1 where seen = 0
Edit
Your updated explanation seems to indicate you want the # of unseen messages for every conversation. If so, select all messages where seen equals 0 and group them by participants using greatest and least.
select least(toid,fmid), greatest(toid,fmid), count(*)
from messages
where seen = 0
group by least(toid,fmid), greatest(toid,fmid)
If you also need to include conversations with no unseen messages (i.e. count=0), then remove the where seen = 0 condition and replace count(*) with sum(seen=0), where seen=0 evaluates to either a 1 or 0.
select least(toid,fmid), greatest(toid,fmid), sum(seen=0)
from messages
group by least(toid,fmid), greatest(toid,fmid)
To select additional columns, join messages to a derived table containing the counts:
select m.*, t1.seen_count from messages m
join (
select least(toid,fmid) leastid, greatest(toid,fmid) greatestid, sum(seen=0) seen_count
from messages
group by least(toid,fmid), greatest(toid,fmid)
) t1 on t1.leastid = least(m.toid,fmid) and t1.greatestid = greatest(m.toid,fmid)
If you just want the count where the seen = 0 use:
SELECT COUNT(*) AS TOTAL FROM messages WHERE seen = 0;
OR
within your query only just add COUNT(*) AS TOTAL before specifying the table's name within your query and WHERE seen = 0 in the where clause.
It'll return all the records with seen = 0 but with an extra column TOTAL.
Hope you wanted this. If you need anything else please explain.
I am trying to join a table into forcing only to show the results of voucherroll that have more than 0 not printed vouchers.
But now I am getting the message that i am using a group function wrong. However, I think I'm not using group by at all.
Any ideas?
SELECT *
FROM voucherroll INNER JOIN voucher ON voucherroll.id = voucher.id_voucherroll
WHERE voucher.printed = 0
AND Count(voucher.id > 0)
An updated explanation:
There are multiple rolls, with multiple vouchers.
if vouchers are printed, they are not supposed to be shown.
I want every roll, where the not printed vouchers are more than 0
You are using count() and it doesn't belong in where.
Perhaps this is your intention?
SELECT *
FROM voucherroll INNER JOIN
voucher
ON voucherroll.id = voucher.id_voucherroll
WHERE voucher.printed = 0 AND voucher.id IS NOT NULL;
It would be unusual, though, for something called id to take on NULL values.
EDIT:
I think this is what you want:
SELECT vr.*
FROM voucherroll vr
WHERE EXISTS (SELECT 1
FROM voucher v
WHERE vr.id = v.id_voucherroll and
v.printed = 0
)
If you want more than 1, then use the less efficient:
SELECT vr.*
FROM voucherroll vr
WHERE (SELECT COUNT(*)
FROM voucher v
WHERE vr.id = v.id_voucherroll and
v.printed = 0
) > 1;
Try to use subquery to count as below:
SELECT *
FROM voucherroll
INNER JOIN voucher ON voucherroll.id = voucher.id_voucherroll
WHERE voucher.printed = 0
AND (select count(v.id)
from voucher v
where voucherroll.id = v.id_voucherroll ) > 0
You can't use count in where clause. It is possible in having clause, but you need to use group by.
I want to get '0' when no records found on execution of sql query. I try so many things like ifnull(count(*),0) but not gives me the result which i want.
Query is mention as below :
SELECT chat_room_id,COUNT(*) FROM chat WHERE sender_id=13 GROUP BY chat_room_id
It gives me the result as below:
__________________________
| chat_room_id | Count(*) |
--------------------------
It not return any 'null' or '0' , so i want to get '0' OR 'null' if no records found.
As long as there is a table Chats with field sender_id then the following will return a row even if the sender_Id 13 does not exist in the table.
set #sender = 13;
set #chats = (select count(*) from Chat where sender_id = #sender);
select #sender AS sender_id, IFNULL(#chats,0) AS Count_chats
;
See this working at SQLFiddle
AFTER YOUR EDIT CHANGES
Try this:
SELECT distinct c1.chat_room_id,
(select count(*) from chat c2 c2.chat_room_id = c1.chat_room_id and c2.sender_id = 13)
FROM chat c1
Pay attention:
A table named CHAT I suppose contains all chats in your DB and no the messages and senders.
Instead if you have a table named CHAT_ROOM with the list of all chats so your query becomes:
SELECT chat_room_id,
(SELECT COUNT(*)
FROM chat
WHERE chat.chat_room_id = chat_room.chat_room_id AND chat.sender_id = 13)
FROM chat_room
You can not query data which is not in the source tables or which is not available with calculation.
If you have a table which contains all available chat rooms, you can use that table to get the desired record with a simple query using LEFT OUTER JOIN
SELECT
CR.chat_room_id,
COUNT(C.chat_room_id)
FROM
chat_rooms CR
LEFT JOIN chat C
ON CR.chat_room_id = C.chat_room_id
AND C.sender_id = 13 -- Moved from WHERE to keep all non-matching records from CR
GROUP BY
CR.chat_room_id
If you do not have a specific table, you can use LEFT OUTER JOIN and a subquery to get the result:
SELECT
CR.chat_room_id,
COUNT(C.chat_room_id)
FROM
(SELECT DISTINCT chat_room_id FROM chat) CR
LEFT JOIN chat C
ON CR.chat_room_id = C.chat_room_id
AND C.sender_id = 13 -- Moved from WHERE to keep all non-matching records from CR
GROUP BY
CR.chat_room_id
SQLFiddle demo for the second query
Are you looking to return all the chat_room_ids in case the sender id does not exist?
like, if say sender_id 9 does not exist, what are you looking to return?
In case you wanted something like
chat_room_id count
NO_RECORDS 0
then the below query will work:
declare #Chat_Room_Id varchar(3),
#Count int
select #Chat_Room_Id = cast(chat_room_id as varchar(3)), #Count = count(*) from chat where sender_id=13 group by chat_room_id
select coalesce(#Chat_Room_Id, 'NO RECORDS') chat_room_id, coalesce(#Count, 0) count
In case I did not understand, can you please clarify further?
-hth
Sourav
you can use mysql_affected_rows(); method to get the details of rows affected with your query.
check this
and this
You can put the sql in a sub query this will always return a row
select sub.id,sub.counter from (select sender_id as id,count(*) as counter from chat where sender_id = 13) sub
This will return 0 if there are no records or 1 if there are.
I have a query
SELECT m1.mid mid, m1.uid uid, m1.date, m1.body body
FROM messages m1
WHERE m1.chat_id IS NULL
and deleted = 0
AND m1.date in
(
SELECT MAX(m2.date)
FROM messages m2
WHERE m2.uid = m1.uid
AND m2.chat_id IS NULL
and m2.deleted = 0
)
This query was not actually written by me, I got help here - hanks them a lot.
But I have a problem. When there is more than one message with the same date and uid(from the same user) values, i get two or more records with the same date and uid, but i'd like to have only one( no matter which, or the message with the greatest mid f.e.)
I've tried to use distinct(uid) with no success result. Is there any other way to achive the result i want?
You can use this solution to find the most recent message per uid:
SELECT b.*
FROM
(
SELECT MAX(mid) AS maxmid
FROM messages
WHERE chat_id IS NULL
GROUP BY uid
) a
INNER JOIN messages b ON a.maxmid = b.mid
Rather you could add an extra column "count" and display the number of messages from a user on the same day!!
By this you can avoid, getting duplicate records!