如果没有记录,则未读邮件计数应返回非零

时间:2018-11-11 13:05:26

标签: mysql

这是我的表结构:

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

正在尝试列出当前登录用户的所有票证。也就是说,仅由他们创建的票证。

此外,正在显示一个小的颜色指示,以使用户知道是否有未读消息。

因此,每当用户查看故障单时(通过从列表中单击),将在记录tblReadBy中将ticket_iduser_id与当前记录一起插入/更新。时间)

我的查询门票清单的查询看起来像这样:

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

此处,XXX是当前登录用户的user_id。如果tblReadBy表中当前登录的user_idticket_id中有一行,则此查询工作正常。

但是如果此user_idticket_id不存在任何行,则按照逻辑,这是“未读票证”,但查询将为0返回has_unread_msg列。

如何解决这种特殊情况?

注意::将有一个以上的用户答复票证。像实际的用户,主持人(不止一个),管理员等。

谢谢


解决方案:

到目前为止,我发现的是:

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

我还在尝试测试所有可能的情况。

3 个答案:

答案 0 :(得分:1)

我们可以使用SUM()函数的[ { "name": "refs/tags/wagner-test-3", "newObjectId": "0000000000000000000000000000000000000000", "oldObjectId": "aaaaab6cad84a07b7bd65cf3519142a12f856baa" } ] 处理行为。如果没有行,它将返回NULL

  

如果返回集没有行,则SUM()返回NULL

MySQL自动将布尔比较运算符的结果类型转换为0/1。通过这种行为,我们可以使用NULLCoalesce()

Sum()

答案 1 :(得分:0)

之所以可行,是因为它离开了两个表的连接,以找出tblReadBy中是否有任何记录,然后在子查询中使用结果。不幸的是我无法测试。

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

您可能需要在外部查询的SELECT列表中添加r。ticket_id,如下所示:

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

答案 2 :(得分:0)

正如我所见,您需要同时统计tblReadBy中已更新的消息和新消息且从未读取过的消息,即它们存在于tblTickets中,但不存在于tblReadBy中。

这是我的解决方案,有点复杂,我希望看到有人对其进行改进,但是基本上我又加入了两个“ SELECT ... COUNT(*)”,一个用于全新消息,一个用于更新

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'