When no records exists, should return non-zero for unread messages count










0














This is my table structure:



tblTickets
ticket_id | subject | creator_id | created_date | last_updated | category_id | ticket_status

tblMessages
msg_id | msg | ticket_id | replied_by | reply_time

tblReadBy - PrimaryKey: (ticket_id,user_id)
ticket_id | user_id | last_read_time


Am trying to list all the tickets to the currently logged in User. That is, tickets that were created by them only.



Also, am showing a small color indication to let the the User know whether there's any unread messages.



So, whenever a User views a Ticket(by clicking from the list), a record will be either inserted/updated in tblReadBy with the ticket_id and user_id along with the current time)



My query for listing Tickets looks somewhat like this:



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT COUNT(*)
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `has_unread_msg`
FROM `tblTickets` AS t
WHERE t.`creator_id` = 'XXX'
ORDER BY t.`last_updated` DESC


Here, XXX is the user_id of the currently logged in User. This query works fine if there's a row in tblReadBy table for the currently logged in user_id and the ticket_id.



But if there's no row exists for this user_id and ticket_id, then as per logic it's an "unread ticket", but the query would return 0 for has_unread_msg column.



How can I fix this particular case?



NOTE: There would be more than one user replying to a Ticket. Like the actual User, Moderator (more than one), Admin, etc.



Thank you




SOLUTION:



So far, what I figured out is this:



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
COALESCE(SUM(CASE WHEN `last_read_time` < t.`last_updated` THEN 1 ELSE 0 END), 1)
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX'
) AS `has_unread_msg`
FROM `tblTickets` AS t
WHERE t.`creator_id` = 'XXX'
ORDER BY t.`last_updated` DESC


Am still trying to test all possible cases.










share|improve this question























  • Your unread_msg_count does not make sense. Instead it should be times_ticket_is_read
    – Madhur Bhaiya
    Nov 11 at 13:19










  • @MadhurBhaiya, like I said earlier, unread_msg_count will work as expected if there's any records for the currently logged in user_id and the ticket_id. But if there's no records, then the logic will fail! There will be more than one person replying to the ticket. Like a User, Admin and Moderator.
    – Vpp Man
    Nov 11 at 13:23










  • As I understand from your table definition and current query, unread_msg_count is basically counting the number of times the use XXX has read this ticket before the ticket has been updated. tblReadBy has only one row for a combination of user_id and ticket_id ??
    – Madhur Bhaiya
    Nov 11 at 13:28










  • @MadhurBhaiya, you can read that column name as has_unread_msg instead of unread_msg_count.
    – Vpp Man
    Nov 11 at 13:31










  • @MadhurBhaiya, I already mentioned that a row in tblReadBy will be either inserted/updated when a User view Ticket (there's separate INSERT .. ON DUPLICATE UPDATE... query behind the scenes, which I didn't posted as it is irrelevant.
    – Vpp Man
    Nov 11 at 13:35















0














This is my table structure:



tblTickets
ticket_id | subject | creator_id | created_date | last_updated | category_id | ticket_status

tblMessages
msg_id | msg | ticket_id | replied_by | reply_time

tblReadBy - PrimaryKey: (ticket_id,user_id)
ticket_id | user_id | last_read_time


Am trying to list all the tickets to the currently logged in User. That is, tickets that were created by them only.



Also, am showing a small color indication to let the the User know whether there's any unread messages.



So, whenever a User views a Ticket(by clicking from the list), a record will be either inserted/updated in tblReadBy with the ticket_id and user_id along with the current time)



My query for listing Tickets looks somewhat like this:



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT COUNT(*)
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `has_unread_msg`
FROM `tblTickets` AS t
WHERE t.`creator_id` = 'XXX'
ORDER BY t.`last_updated` DESC


Here, XXX is the user_id of the currently logged in User. This query works fine if there's a row in tblReadBy table for the currently logged in user_id and the ticket_id.



But if there's no row exists for this user_id and ticket_id, then as per logic it's an "unread ticket", but the query would return 0 for has_unread_msg column.



How can I fix this particular case?



NOTE: There would be more than one user replying to a Ticket. Like the actual User, Moderator (more than one), Admin, etc.



Thank you




SOLUTION:



So far, what I figured out is this:



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
COALESCE(SUM(CASE WHEN `last_read_time` < t.`last_updated` THEN 1 ELSE 0 END), 1)
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX'
) AS `has_unread_msg`
FROM `tblTickets` AS t
WHERE t.`creator_id` = 'XXX'
ORDER BY t.`last_updated` DESC


Am still trying to test all possible cases.










share|improve this question























  • Your unread_msg_count does not make sense. Instead it should be times_ticket_is_read
    – Madhur Bhaiya
    Nov 11 at 13:19










  • @MadhurBhaiya, like I said earlier, unread_msg_count will work as expected if there's any records for the currently logged in user_id and the ticket_id. But if there's no records, then the logic will fail! There will be more than one person replying to the ticket. Like a User, Admin and Moderator.
    – Vpp Man
    Nov 11 at 13:23










  • As I understand from your table definition and current query, unread_msg_count is basically counting the number of times the use XXX has read this ticket before the ticket has been updated. tblReadBy has only one row for a combination of user_id and ticket_id ??
    – Madhur Bhaiya
    Nov 11 at 13:28










  • @MadhurBhaiya, you can read that column name as has_unread_msg instead of unread_msg_count.
    – Vpp Man
    Nov 11 at 13:31










  • @MadhurBhaiya, I already mentioned that a row in tblReadBy will be either inserted/updated when a User view Ticket (there's separate INSERT .. ON DUPLICATE UPDATE... query behind the scenes, which I didn't posted as it is irrelevant.
    – Vpp Man
    Nov 11 at 13:35













0












0








0







This is my table structure:



tblTickets
ticket_id | subject | creator_id | created_date | last_updated | category_id | ticket_status

tblMessages
msg_id | msg | ticket_id | replied_by | reply_time

tblReadBy - PrimaryKey: (ticket_id,user_id)
ticket_id | user_id | last_read_time


Am trying to list all the tickets to the currently logged in User. That is, tickets that were created by them only.



Also, am showing a small color indication to let the the User know whether there's any unread messages.



So, whenever a User views a Ticket(by clicking from the list), a record will be either inserted/updated in tblReadBy with the ticket_id and user_id along with the current time)



My query for listing Tickets looks somewhat like this:



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT COUNT(*)
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `has_unread_msg`
FROM `tblTickets` AS t
WHERE t.`creator_id` = 'XXX'
ORDER BY t.`last_updated` DESC


Here, XXX is the user_id of the currently logged in User. This query works fine if there's a row in tblReadBy table for the currently logged in user_id and the ticket_id.



But if there's no row exists for this user_id and ticket_id, then as per logic it's an "unread ticket", but the query would return 0 for has_unread_msg column.



How can I fix this particular case?



NOTE: There would be more than one user replying to a Ticket. Like the actual User, Moderator (more than one), Admin, etc.



Thank you




SOLUTION:



So far, what I figured out is this:



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
COALESCE(SUM(CASE WHEN `last_read_time` < t.`last_updated` THEN 1 ELSE 0 END), 1)
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX'
) AS `has_unread_msg`
FROM `tblTickets` AS t
WHERE t.`creator_id` = 'XXX'
ORDER BY t.`last_updated` DESC


Am still trying to test all possible cases.










share|improve this question















This is my table structure:



tblTickets
ticket_id | subject | creator_id | created_date | last_updated | category_id | ticket_status

tblMessages
msg_id | msg | ticket_id | replied_by | reply_time

tblReadBy - PrimaryKey: (ticket_id,user_id)
ticket_id | user_id | last_read_time


Am trying to list all the tickets to the currently logged in User. That is, tickets that were created by them only.



Also, am showing a small color indication to let the the User know whether there's any unread messages.



So, whenever a User views a Ticket(by clicking from the list), a record will be either inserted/updated in tblReadBy with the ticket_id and user_id along with the current time)



My query for listing Tickets looks somewhat like this:



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT COUNT(*)
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `has_unread_msg`
FROM `tblTickets` AS t
WHERE t.`creator_id` = 'XXX'
ORDER BY t.`last_updated` DESC


Here, XXX is the user_id of the currently logged in User. This query works fine if there's a row in tblReadBy table for the currently logged in user_id and the ticket_id.



But if there's no row exists for this user_id and ticket_id, then as per logic it's an "unread ticket", but the query would return 0 for has_unread_msg column.



How can I fix this particular case?



NOTE: There would be more than one user replying to a Ticket. Like the actual User, Moderator (more than one), Admin, etc.



Thank you




SOLUTION:



So far, what I figured out is this:



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
COALESCE(SUM(CASE WHEN `last_read_time` < t.`last_updated` THEN 1 ELSE 0 END), 1)
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX'
) AS `has_unread_msg`
FROM `tblTickets` AS t
WHERE t.`creator_id` = 'XXX'
ORDER BY t.`last_updated` DESC


Am still trying to test all possible cases.







mysql






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 11 at 14:20

























asked Nov 11 at 13:05









Vpp Man

81142453




81142453











  • Your unread_msg_count does not make sense. Instead it should be times_ticket_is_read
    – Madhur Bhaiya
    Nov 11 at 13:19










  • @MadhurBhaiya, like I said earlier, unread_msg_count will work as expected if there's any records for the currently logged in user_id and the ticket_id. But if there's no records, then the logic will fail! There will be more than one person replying to the ticket. Like a User, Admin and Moderator.
    – Vpp Man
    Nov 11 at 13:23










  • As I understand from your table definition and current query, unread_msg_count is basically counting the number of times the use XXX has read this ticket before the ticket has been updated. tblReadBy has only one row for a combination of user_id and ticket_id ??
    – Madhur Bhaiya
    Nov 11 at 13:28










  • @MadhurBhaiya, you can read that column name as has_unread_msg instead of unread_msg_count.
    – Vpp Man
    Nov 11 at 13:31










  • @MadhurBhaiya, I already mentioned that a row in tblReadBy will be either inserted/updated when a User view Ticket (there's separate INSERT .. ON DUPLICATE UPDATE... query behind the scenes, which I didn't posted as it is irrelevant.
    – Vpp Man
    Nov 11 at 13:35
















  • Your unread_msg_count does not make sense. Instead it should be times_ticket_is_read
    – Madhur Bhaiya
    Nov 11 at 13:19










  • @MadhurBhaiya, like I said earlier, unread_msg_count will work as expected if there's any records for the currently logged in user_id and the ticket_id. But if there's no records, then the logic will fail! There will be more than one person replying to the ticket. Like a User, Admin and Moderator.
    – Vpp Man
    Nov 11 at 13:23










  • As I understand from your table definition and current query, unread_msg_count is basically counting the number of times the use XXX has read this ticket before the ticket has been updated. tblReadBy has only one row for a combination of user_id and ticket_id ??
    – Madhur Bhaiya
    Nov 11 at 13:28










  • @MadhurBhaiya, you can read that column name as has_unread_msg instead of unread_msg_count.
    – Vpp Man
    Nov 11 at 13:31










  • @MadhurBhaiya, I already mentioned that a row in tblReadBy will be either inserted/updated when a User view Ticket (there's separate INSERT .. ON DUPLICATE UPDATE... query behind the scenes, which I didn't posted as it is irrelevant.
    – Vpp Man
    Nov 11 at 13:35















Your unread_msg_count does not make sense. Instead it should be times_ticket_is_read
– Madhur Bhaiya
Nov 11 at 13:19




Your unread_msg_count does not make sense. Instead it should be times_ticket_is_read
– Madhur Bhaiya
Nov 11 at 13:19












@MadhurBhaiya, like I said earlier, unread_msg_count will work as expected if there's any records for the currently logged in user_id and the ticket_id. But if there's no records, then the logic will fail! There will be more than one person replying to the ticket. Like a User, Admin and Moderator.
– Vpp Man
Nov 11 at 13:23




@MadhurBhaiya, like I said earlier, unread_msg_count will work as expected if there's any records for the currently logged in user_id and the ticket_id. But if there's no records, then the logic will fail! There will be more than one person replying to the ticket. Like a User, Admin and Moderator.
– Vpp Man
Nov 11 at 13:23












As I understand from your table definition and current query, unread_msg_count is basically counting the number of times the use XXX has read this ticket before the ticket has been updated. tblReadBy has only one row for a combination of user_id and ticket_id ??
– Madhur Bhaiya
Nov 11 at 13:28




As I understand from your table definition and current query, unread_msg_count is basically counting the number of times the use XXX has read this ticket before the ticket has been updated. tblReadBy has only one row for a combination of user_id and ticket_id ??
– Madhur Bhaiya
Nov 11 at 13:28












@MadhurBhaiya, you can read that column name as has_unread_msg instead of unread_msg_count.
– Vpp Man
Nov 11 at 13:31




@MadhurBhaiya, you can read that column name as has_unread_msg instead of unread_msg_count.
– Vpp Man
Nov 11 at 13:31












@MadhurBhaiya, I already mentioned that a row in tblReadBy will be either inserted/updated when a User view Ticket (there's separate INSERT .. ON DUPLICATE UPDATE... query behind the scenes, which I didn't posted as it is irrelevant.
– Vpp Man
Nov 11 at 13:35




@MadhurBhaiya, I already mentioned that a row in tblReadBy will be either inserted/updated when a User view Ticket (there's separate INSERT .. ON DUPLICATE UPDATE... query behind the scenes, which I didn't posted as it is irrelevant.
– Vpp Man
Nov 11 at 13:35












3 Answers
3






active

oldest

votes


















1














We can use SUM() function's NULL handling behavior. It will return NULL if no row exists.




If the return set has no rows, SUM() returns NULL




MySQL automatically typecasts results of a Boolean comparison operator to 0/1. Using this behavior, we can can use Sum() and Coalesce().



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
-- coalesce handles case when no rows
SELECT COALESCE(SUM(`ticket_id` > 0), 1)
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `has_unread_msg`
FROM `tblTickets` AS t
WHERE t.`creator_id` = 'XXX'
ORDER BY t.`last_updated` DESC





share|improve this answer






















  • @VppMan check the updated answer; use the part below the horizontal line
    – Madhur Bhaiya
    Nov 11 at 14:06










  • Bhauya, this is what seems to be working: SELECT COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) FROM tblReadBy WHERE ticket_id = t.ticket_id AND user_id = 'XXX'
    – Vpp Man
    Nov 11 at 14:24











  • @VppMan replace COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) with COALESCE(SUM(ticket_id IS NOT NULL), 1)
    – Madhur Bhaiya
    Nov 11 at 14:25











  • I don't think what you suggested will work. Because in the WHERE condition last_read_time < t.last_updated is used. Which will fetch only those rows that matches that condition! So using SUM() on those rows again breaks the logic!
    – Vpp Man
    Nov 11 at 14:35










  • @VppMan have you tried my code ? Can you create a fiddle to prove the same. Based on my understanding, my solution should work.
    – Madhur Bhaiya
    Nov 11 at 14:37


















0














As I see it you need to count both messages that has been update in tblReadBy and messages that are new and have never been read, that is they exists in tblTickets but not in tblReadBy.



Here is my solution that is a bit complicated, I would love to see someone improve it, but basically I join agains two `SELECT ... COUNT(*)´, one for completely new messages and one for updated



SELECT t.ticket_id, subject, t.user_id, created_date, last_updated, IFNULL(c1.count, 0) + IFNULL(c2.count, 0)
FROM tblTickets t
LEFT JOIN (SELECT ticket_id, user_id, COUNT(*) count
FROM tblTickets t
WHERE NOT EXISTS (SELECT *
FROM tblReadBy r
WHERE t.ticket_id = r.ticket_id
AND t.user_id = r.user_id)
GROUP BY ticket_id, user_id) AS c1 ON c1.ticket_id = t.ticket_id AND c1.user_id = t.user_id
LEFT JOIN (SELECT r.ticket_id, r.user_id, COUNT(*) count
FROM tblReadBy r
JOIN tblTickets t ON t.ticket_id = r.ticket_id AND t.user_id = r.user_id
WHERE r.last_read_time < t.last_updated
GROUP BY r.ticket_id, r.user_id) AS c2 ON c2.ticket_id = t.ticket_id AND c2.user_id = t.user_id
WHERE t.user_id = 'aaa'





share|improve this answer




















  • Thank you. It looks a bit complex. Am trying to understand the idea from your query first.
    – Vpp Man
    Nov 11 at 14:33


















0














This could work because it left joins the two tables to find out whether there are any records in tblReadBy and then uses the result in the subquery. Unfortunately I couldn't test it.



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
CASE WHEN r.`ticket_id` IS NULL THEN 1
ELSE COUNT(*)
END AS message_count
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `unread_msg_count`
FROM `tblTickets` AS t
LEFT JOIN `tblReadBy` AS r ON t.`ticket_id` = r.`ticket_id` AND
r.`user_id` = 'XXX'
ORDER BY t.`last_updated` DESC


You might need to add r.ticket_id in the SELECT list of the outer query like so:



SELECT 
t.`ticket_id`,
r.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
CASE WHEN r.`ticket_id` IS NULL THEN 1
ELSE COUNT(*)
END AS message_count
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `unread_msg_count`
FROM `tblTickets` AS t
LEFT JOIN `tblReadBy` AS r ON t.`ticket_id` = r.`ticket_id` AND
r.`user_id` = 'XXX'
ORDER BY t.`last_updated` DESC





share|improve this answer






















  • thank you. It worked! But it will give duplicate records if there's more than one rows for the same Ticket in tblReadBy (because there will be more than one person replying to the same Ticket). So I added a GROUP BY t.ticket_id in the outer query. Its okay right?
    – Vpp Man
    Nov 11 at 14:03











  • ok, got it. I modified the LEFT JOIN to only select tickets from the respective user (if any) or to return NULL if there aren't any.
    – rf1234
    Nov 11 at 14:40










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53249022%2fwhen-no-records-exists-should-return-non-zero-for-unread-messages-count%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














We can use SUM() function's NULL handling behavior. It will return NULL if no row exists.




If the return set has no rows, SUM() returns NULL




MySQL automatically typecasts results of a Boolean comparison operator to 0/1. Using this behavior, we can can use Sum() and Coalesce().



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
-- coalesce handles case when no rows
SELECT COALESCE(SUM(`ticket_id` > 0), 1)
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `has_unread_msg`
FROM `tblTickets` AS t
WHERE t.`creator_id` = 'XXX'
ORDER BY t.`last_updated` DESC





share|improve this answer






















  • @VppMan check the updated answer; use the part below the horizontal line
    – Madhur Bhaiya
    Nov 11 at 14:06










  • Bhauya, this is what seems to be working: SELECT COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) FROM tblReadBy WHERE ticket_id = t.ticket_id AND user_id = 'XXX'
    – Vpp Man
    Nov 11 at 14:24











  • @VppMan replace COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) with COALESCE(SUM(ticket_id IS NOT NULL), 1)
    – Madhur Bhaiya
    Nov 11 at 14:25











  • I don't think what you suggested will work. Because in the WHERE condition last_read_time < t.last_updated is used. Which will fetch only those rows that matches that condition! So using SUM() on those rows again breaks the logic!
    – Vpp Man
    Nov 11 at 14:35










  • @VppMan have you tried my code ? Can you create a fiddle to prove the same. Based on my understanding, my solution should work.
    – Madhur Bhaiya
    Nov 11 at 14:37















1














We can use SUM() function's NULL handling behavior. It will return NULL if no row exists.




If the return set has no rows, SUM() returns NULL




MySQL automatically typecasts results of a Boolean comparison operator to 0/1. Using this behavior, we can can use Sum() and Coalesce().



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
-- coalesce handles case when no rows
SELECT COALESCE(SUM(`ticket_id` > 0), 1)
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `has_unread_msg`
FROM `tblTickets` AS t
WHERE t.`creator_id` = 'XXX'
ORDER BY t.`last_updated` DESC





share|improve this answer






















  • @VppMan check the updated answer; use the part below the horizontal line
    – Madhur Bhaiya
    Nov 11 at 14:06










  • Bhauya, this is what seems to be working: SELECT COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) FROM tblReadBy WHERE ticket_id = t.ticket_id AND user_id = 'XXX'
    – Vpp Man
    Nov 11 at 14:24











  • @VppMan replace COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) with COALESCE(SUM(ticket_id IS NOT NULL), 1)
    – Madhur Bhaiya
    Nov 11 at 14:25











  • I don't think what you suggested will work. Because in the WHERE condition last_read_time < t.last_updated is used. Which will fetch only those rows that matches that condition! So using SUM() on those rows again breaks the logic!
    – Vpp Man
    Nov 11 at 14:35










  • @VppMan have you tried my code ? Can you create a fiddle to prove the same. Based on my understanding, my solution should work.
    – Madhur Bhaiya
    Nov 11 at 14:37













1












1








1






We can use SUM() function's NULL handling behavior. It will return NULL if no row exists.




If the return set has no rows, SUM() returns NULL




MySQL automatically typecasts results of a Boolean comparison operator to 0/1. Using this behavior, we can can use Sum() and Coalesce().



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
-- coalesce handles case when no rows
SELECT COALESCE(SUM(`ticket_id` > 0), 1)
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `has_unread_msg`
FROM `tblTickets` AS t
WHERE t.`creator_id` = 'XXX'
ORDER BY t.`last_updated` DESC





share|improve this answer














We can use SUM() function's NULL handling behavior. It will return NULL if no row exists.




If the return set has no rows, SUM() returns NULL




MySQL automatically typecasts results of a Boolean comparison operator to 0/1. Using this behavior, we can can use Sum() and Coalesce().



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
-- coalesce handles case when no rows
SELECT COALESCE(SUM(`ticket_id` > 0), 1)
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `has_unread_msg`
FROM `tblTickets` AS t
WHERE t.`creator_id` = 'XXX'
ORDER BY t.`last_updated` DESC






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 11 at 14:27

























answered Nov 11 at 13:15









Madhur Bhaiya

19.5k62236




19.5k62236











  • @VppMan check the updated answer; use the part below the horizontal line
    – Madhur Bhaiya
    Nov 11 at 14:06










  • Bhauya, this is what seems to be working: SELECT COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) FROM tblReadBy WHERE ticket_id = t.ticket_id AND user_id = 'XXX'
    – Vpp Man
    Nov 11 at 14:24











  • @VppMan replace COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) with COALESCE(SUM(ticket_id IS NOT NULL), 1)
    – Madhur Bhaiya
    Nov 11 at 14:25











  • I don't think what you suggested will work. Because in the WHERE condition last_read_time < t.last_updated is used. Which will fetch only those rows that matches that condition! So using SUM() on those rows again breaks the logic!
    – Vpp Man
    Nov 11 at 14:35










  • @VppMan have you tried my code ? Can you create a fiddle to prove the same. Based on my understanding, my solution should work.
    – Madhur Bhaiya
    Nov 11 at 14:37
















  • @VppMan check the updated answer; use the part below the horizontal line
    – Madhur Bhaiya
    Nov 11 at 14:06










  • Bhauya, this is what seems to be working: SELECT COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) FROM tblReadBy WHERE ticket_id = t.ticket_id AND user_id = 'XXX'
    – Vpp Man
    Nov 11 at 14:24











  • @VppMan replace COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) with COALESCE(SUM(ticket_id IS NOT NULL), 1)
    – Madhur Bhaiya
    Nov 11 at 14:25











  • I don't think what you suggested will work. Because in the WHERE condition last_read_time < t.last_updated is used. Which will fetch only those rows that matches that condition! So using SUM() on those rows again breaks the logic!
    – Vpp Man
    Nov 11 at 14:35










  • @VppMan have you tried my code ? Can you create a fiddle to prove the same. Based on my understanding, my solution should work.
    – Madhur Bhaiya
    Nov 11 at 14:37















@VppMan check the updated answer; use the part below the horizontal line
– Madhur Bhaiya
Nov 11 at 14:06




@VppMan check the updated answer; use the part below the horizontal line
– Madhur Bhaiya
Nov 11 at 14:06












Bhauya, this is what seems to be working: SELECT COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) FROM tblReadBy WHERE ticket_id = t.ticket_id AND user_id = 'XXX'
– Vpp Man
Nov 11 at 14:24





Bhauya, this is what seems to be working: SELECT COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) FROM tblReadBy WHERE ticket_id = t.ticket_id AND user_id = 'XXX'
– Vpp Man
Nov 11 at 14:24













@VppMan replace COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) with COALESCE(SUM(ticket_id IS NOT NULL), 1)
– Madhur Bhaiya
Nov 11 at 14:25





@VppMan replace COALESCE(SUM(CASE WHEN last_read_time < t.last_updated THEN 1 ELSE 0 END), 1) with COALESCE(SUM(ticket_id IS NOT NULL), 1)
– Madhur Bhaiya
Nov 11 at 14:25













I don't think what you suggested will work. Because in the WHERE condition last_read_time < t.last_updated is used. Which will fetch only those rows that matches that condition! So using SUM() on those rows again breaks the logic!
– Vpp Man
Nov 11 at 14:35




I don't think what you suggested will work. Because in the WHERE condition last_read_time < t.last_updated is used. Which will fetch only those rows that matches that condition! So using SUM() on those rows again breaks the logic!
– Vpp Man
Nov 11 at 14:35












@VppMan have you tried my code ? Can you create a fiddle to prove the same. Based on my understanding, my solution should work.
– Madhur Bhaiya
Nov 11 at 14:37




@VppMan have you tried my code ? Can you create a fiddle to prove the same. Based on my understanding, my solution should work.
– Madhur Bhaiya
Nov 11 at 14:37













0














As I see it you need to count both messages that has been update in tblReadBy and messages that are new and have never been read, that is they exists in tblTickets but not in tblReadBy.



Here is my solution that is a bit complicated, I would love to see someone improve it, but basically I join agains two `SELECT ... COUNT(*)´, one for completely new messages and one for updated



SELECT t.ticket_id, subject, t.user_id, created_date, last_updated, IFNULL(c1.count, 0) + IFNULL(c2.count, 0)
FROM tblTickets t
LEFT JOIN (SELECT ticket_id, user_id, COUNT(*) count
FROM tblTickets t
WHERE NOT EXISTS (SELECT *
FROM tblReadBy r
WHERE t.ticket_id = r.ticket_id
AND t.user_id = r.user_id)
GROUP BY ticket_id, user_id) AS c1 ON c1.ticket_id = t.ticket_id AND c1.user_id = t.user_id
LEFT JOIN (SELECT r.ticket_id, r.user_id, COUNT(*) count
FROM tblReadBy r
JOIN tblTickets t ON t.ticket_id = r.ticket_id AND t.user_id = r.user_id
WHERE r.last_read_time < t.last_updated
GROUP BY r.ticket_id, r.user_id) AS c2 ON c2.ticket_id = t.ticket_id AND c2.user_id = t.user_id
WHERE t.user_id = 'aaa'





share|improve this answer




















  • Thank you. It looks a bit complex. Am trying to understand the idea from your query first.
    – Vpp Man
    Nov 11 at 14:33















0














As I see it you need to count both messages that has been update in tblReadBy and messages that are new and have never been read, that is they exists in tblTickets but not in tblReadBy.



Here is my solution that is a bit complicated, I would love to see someone improve it, but basically I join agains two `SELECT ... COUNT(*)´, one for completely new messages and one for updated



SELECT t.ticket_id, subject, t.user_id, created_date, last_updated, IFNULL(c1.count, 0) + IFNULL(c2.count, 0)
FROM tblTickets t
LEFT JOIN (SELECT ticket_id, user_id, COUNT(*) count
FROM tblTickets t
WHERE NOT EXISTS (SELECT *
FROM tblReadBy r
WHERE t.ticket_id = r.ticket_id
AND t.user_id = r.user_id)
GROUP BY ticket_id, user_id) AS c1 ON c1.ticket_id = t.ticket_id AND c1.user_id = t.user_id
LEFT JOIN (SELECT r.ticket_id, r.user_id, COUNT(*) count
FROM tblReadBy r
JOIN tblTickets t ON t.ticket_id = r.ticket_id AND t.user_id = r.user_id
WHERE r.last_read_time < t.last_updated
GROUP BY r.ticket_id, r.user_id) AS c2 ON c2.ticket_id = t.ticket_id AND c2.user_id = t.user_id
WHERE t.user_id = 'aaa'





share|improve this answer




















  • Thank you. It looks a bit complex. Am trying to understand the idea from your query first.
    – Vpp Man
    Nov 11 at 14:33













0












0








0






As I see it you need to count both messages that has been update in tblReadBy and messages that are new and have never been read, that is they exists in tblTickets but not in tblReadBy.



Here is my solution that is a bit complicated, I would love to see someone improve it, but basically I join agains two `SELECT ... COUNT(*)´, one for completely new messages and one for updated



SELECT t.ticket_id, subject, t.user_id, created_date, last_updated, IFNULL(c1.count, 0) + IFNULL(c2.count, 0)
FROM tblTickets t
LEFT JOIN (SELECT ticket_id, user_id, COUNT(*) count
FROM tblTickets t
WHERE NOT EXISTS (SELECT *
FROM tblReadBy r
WHERE t.ticket_id = r.ticket_id
AND t.user_id = r.user_id)
GROUP BY ticket_id, user_id) AS c1 ON c1.ticket_id = t.ticket_id AND c1.user_id = t.user_id
LEFT JOIN (SELECT r.ticket_id, r.user_id, COUNT(*) count
FROM tblReadBy r
JOIN tblTickets t ON t.ticket_id = r.ticket_id AND t.user_id = r.user_id
WHERE r.last_read_time < t.last_updated
GROUP BY r.ticket_id, r.user_id) AS c2 ON c2.ticket_id = t.ticket_id AND c2.user_id = t.user_id
WHERE t.user_id = 'aaa'





share|improve this answer












As I see it you need to count both messages that has been update in tblReadBy and messages that are new and have never been read, that is they exists in tblTickets but not in tblReadBy.



Here is my solution that is a bit complicated, I would love to see someone improve it, but basically I join agains two `SELECT ... COUNT(*)´, one for completely new messages and one for updated



SELECT t.ticket_id, subject, t.user_id, created_date, last_updated, IFNULL(c1.count, 0) + IFNULL(c2.count, 0)
FROM tblTickets t
LEFT JOIN (SELECT ticket_id, user_id, COUNT(*) count
FROM tblTickets t
WHERE NOT EXISTS (SELECT *
FROM tblReadBy r
WHERE t.ticket_id = r.ticket_id
AND t.user_id = r.user_id)
GROUP BY ticket_id, user_id) AS c1 ON c1.ticket_id = t.ticket_id AND c1.user_id = t.user_id
LEFT JOIN (SELECT r.ticket_id, r.user_id, COUNT(*) count
FROM tblReadBy r
JOIN tblTickets t ON t.ticket_id = r.ticket_id AND t.user_id = r.user_id
WHERE r.last_read_time < t.last_updated
GROUP BY r.ticket_id, r.user_id) AS c2 ON c2.ticket_id = t.ticket_id AND c2.user_id = t.user_id
WHERE t.user_id = 'aaa'






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 11 at 14:11









Joakim Danielson

6,6833623




6,6833623











  • Thank you. It looks a bit complex. Am trying to understand the idea from your query first.
    – Vpp Man
    Nov 11 at 14:33
















  • Thank you. It looks a bit complex. Am trying to understand the idea from your query first.
    – Vpp Man
    Nov 11 at 14:33















Thank you. It looks a bit complex. Am trying to understand the idea from your query first.
– Vpp Man
Nov 11 at 14:33




Thank you. It looks a bit complex. Am trying to understand the idea from your query first.
– Vpp Man
Nov 11 at 14:33











0














This could work because it left joins the two tables to find out whether there are any records in tblReadBy and then uses the result in the subquery. Unfortunately I couldn't test it.



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
CASE WHEN r.`ticket_id` IS NULL THEN 1
ELSE COUNT(*)
END AS message_count
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `unread_msg_count`
FROM `tblTickets` AS t
LEFT JOIN `tblReadBy` AS r ON t.`ticket_id` = r.`ticket_id` AND
r.`user_id` = 'XXX'
ORDER BY t.`last_updated` DESC


You might need to add r.ticket_id in the SELECT list of the outer query like so:



SELECT 
t.`ticket_id`,
r.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
CASE WHEN r.`ticket_id` IS NULL THEN 1
ELSE COUNT(*)
END AS message_count
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `unread_msg_count`
FROM `tblTickets` AS t
LEFT JOIN `tblReadBy` AS r ON t.`ticket_id` = r.`ticket_id` AND
r.`user_id` = 'XXX'
ORDER BY t.`last_updated` DESC





share|improve this answer






















  • thank you. It worked! But it will give duplicate records if there's more than one rows for the same Ticket in tblReadBy (because there will be more than one person replying to the same Ticket). So I added a GROUP BY t.ticket_id in the outer query. Its okay right?
    – Vpp Man
    Nov 11 at 14:03











  • ok, got it. I modified the LEFT JOIN to only select tickets from the respective user (if any) or to return NULL if there aren't any.
    – rf1234
    Nov 11 at 14:40















0














This could work because it left joins the two tables to find out whether there are any records in tblReadBy and then uses the result in the subquery. Unfortunately I couldn't test it.



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
CASE WHEN r.`ticket_id` IS NULL THEN 1
ELSE COUNT(*)
END AS message_count
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `unread_msg_count`
FROM `tblTickets` AS t
LEFT JOIN `tblReadBy` AS r ON t.`ticket_id` = r.`ticket_id` AND
r.`user_id` = 'XXX'
ORDER BY t.`last_updated` DESC


You might need to add r.ticket_id in the SELECT list of the outer query like so:



SELECT 
t.`ticket_id`,
r.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
CASE WHEN r.`ticket_id` IS NULL THEN 1
ELSE COUNT(*)
END AS message_count
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `unread_msg_count`
FROM `tblTickets` AS t
LEFT JOIN `tblReadBy` AS r ON t.`ticket_id` = r.`ticket_id` AND
r.`user_id` = 'XXX'
ORDER BY t.`last_updated` DESC





share|improve this answer






















  • thank you. It worked! But it will give duplicate records if there's more than one rows for the same Ticket in tblReadBy (because there will be more than one person replying to the same Ticket). So I added a GROUP BY t.ticket_id in the outer query. Its okay right?
    – Vpp Man
    Nov 11 at 14:03











  • ok, got it. I modified the LEFT JOIN to only select tickets from the respective user (if any) or to return NULL if there aren't any.
    – rf1234
    Nov 11 at 14:40













0












0








0






This could work because it left joins the two tables to find out whether there are any records in tblReadBy and then uses the result in the subquery. Unfortunately I couldn't test it.



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
CASE WHEN r.`ticket_id` IS NULL THEN 1
ELSE COUNT(*)
END AS message_count
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `unread_msg_count`
FROM `tblTickets` AS t
LEFT JOIN `tblReadBy` AS r ON t.`ticket_id` = r.`ticket_id` AND
r.`user_id` = 'XXX'
ORDER BY t.`last_updated` DESC


You might need to add r.ticket_id in the SELECT list of the outer query like so:



SELECT 
t.`ticket_id`,
r.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
CASE WHEN r.`ticket_id` IS NULL THEN 1
ELSE COUNT(*)
END AS message_count
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `unread_msg_count`
FROM `tblTickets` AS t
LEFT JOIN `tblReadBy` AS r ON t.`ticket_id` = r.`ticket_id` AND
r.`user_id` = 'XXX'
ORDER BY t.`last_updated` DESC





share|improve this answer














This could work because it left joins the two tables to find out whether there are any records in tblReadBy and then uses the result in the subquery. Unfortunately I couldn't test it.



SELECT 
t.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
CASE WHEN r.`ticket_id` IS NULL THEN 1
ELSE COUNT(*)
END AS message_count
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `unread_msg_count`
FROM `tblTickets` AS t
LEFT JOIN `tblReadBy` AS r ON t.`ticket_id` = r.`ticket_id` AND
r.`user_id` = 'XXX'
ORDER BY t.`last_updated` DESC


You might need to add r.ticket_id in the SELECT list of the outer query like so:



SELECT 
t.`ticket_id`,
r.`ticket_id`,
t.`subject`,
t.`user_id`,
t.`created_date`,
t.`last_updated`
(
SELECT
CASE WHEN r.`ticket_id` IS NULL THEN 1
ELSE COUNT(*)
END AS message_count
FROM `tblReadBy`
WHERE `ticket_id` = t.`ticket_id` AND
`user_id` = 'XXX' AND
`last_read_time` < t.`last_updated`
) AS `unread_msg_count`
FROM `tblTickets` AS t
LEFT JOIN `tblReadBy` AS r ON t.`ticket_id` = r.`ticket_id` AND
r.`user_id` = 'XXX'
ORDER BY t.`last_updated` DESC






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 11 at 14:42

























answered Nov 11 at 13:34









rf1234

40257




40257











  • thank you. It worked! But it will give duplicate records if there's more than one rows for the same Ticket in tblReadBy (because there will be more than one person replying to the same Ticket). So I added a GROUP BY t.ticket_id in the outer query. Its okay right?
    – Vpp Man
    Nov 11 at 14:03











  • ok, got it. I modified the LEFT JOIN to only select tickets from the respective user (if any) or to return NULL if there aren't any.
    – rf1234
    Nov 11 at 14:40
















  • thank you. It worked! But it will give duplicate records if there's more than one rows for the same Ticket in tblReadBy (because there will be more than one person replying to the same Ticket). So I added a GROUP BY t.ticket_id in the outer query. Its okay right?
    – Vpp Man
    Nov 11 at 14:03











  • ok, got it. I modified the LEFT JOIN to only select tickets from the respective user (if any) or to return NULL if there aren't any.
    – rf1234
    Nov 11 at 14:40















thank you. It worked! But it will give duplicate records if there's more than one rows for the same Ticket in tblReadBy (because there will be more than one person replying to the same Ticket). So I added a GROUP BY t.ticket_id in the outer query. Its okay right?
– Vpp Man
Nov 11 at 14:03





thank you. It worked! But it will give duplicate records if there's more than one rows for the same Ticket in tblReadBy (because there will be more than one person replying to the same Ticket). So I added a GROUP BY t.ticket_id in the outer query. Its okay right?
– Vpp Man
Nov 11 at 14:03













ok, got it. I modified the LEFT JOIN to only select tickets from the respective user (if any) or to return NULL if there aren't any.
– rf1234
Nov 11 at 14:40




ok, got it. I modified the LEFT JOIN to only select tickets from the respective user (if any) or to return NULL if there aren't any.
– rf1234
Nov 11 at 14:40

















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53249022%2fwhen-no-records-exists-should-return-non-zero-for-unread-messages-count%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Ruanda

Makov (Slowakei)

Kleinkühnau