【问题标题】:MySQL combining complex queries and optimizing functionalityMySQL结合了复杂的查询和优化功能
【发布时间】:2012-10-19 04:40:09
【问题描述】:

我正在开发一个相当复杂的通知系统,它在大多数情况下都非常简单,复杂性在于检查其他表是否内容已被删除,并且我有多个数据表全部进入通知系统,因此它必须检查每一个,并且我必须能够在构建网站时轻松添加更多表以允许添加其他通知类型,并且使用当前查询我正在使用它不允许这样做,我试图想出一个更好的方法来做到这一点,但是我对 mysql 查询做得不够好,所以我希望我能得到一些(或者它可能会变成得到你们中的一个(或一些)的帮助。

这是我当前的查询:

SELECT
    n.*,
    MIN(n.state) state,
    MIN(n.status) status,
    MAX(n.date) maxDate
FROM notifications n
LEFT JOIN comments c 
     ON n.type = 'comment' 
     AND n.uniqueID = c.id  
     AND c.state='0'
LEFT JOIN posts p 
     ON n.type = 'post' 
     AND p.id = n.uniqueID OR n.type = 'comment' 
     AND p.id = c.postID

WHERE n.toID = '$session'
AND p.state = 0
GROUP BY n.uniqueID
ORDER BY status ASC, maxDate DESC

那么,简而言之,上述语句的作用就是这样。它从通知表中选择通知,在此表中有一个列用于该内容的typeuniqueID。因此,对于类型为 posts 的每一行,它会检查帖子表,其中通知中的 uniqueID 与帖子表中的唯一 ID 相同,然后检查该帖子的 state 以查看它是否有是否被删除(如果它没有被删除,state=0,否则我不想要它)。 cmets也是如此。

所以我需要一种方法来做所有事情,就像这样做一样,但是我需要更容易不断地向它添加新的表检查。我一直在尝试为一个名为 likes 的表添加另一个左连接,但是无论出于何种原因,我都无法让它一起工作。但是我想出了这个代码,它可以做我想做的事情。 (但仅适用于 likes 表,它不包括我需要的任何其他表)

SELECT
    n.*,
    MIN(n.state) state,
    MIN(n.status) status,
    MAX(n.date) maxDate
FROM notifications n
LEFT JOIN likes l 
     ON n.type = 'likes' 
     AND n.uniqueID = l.id 
WHERE n.toID = '$session'
AND l.state='0'
GROUP BY n.uniqueID
ORDER BY status ASC, maxDate DESC

我希望有人可以帮助我解决这个问题,非常感谢您!

【问题讨论】:

    标签: php mysql join mysqli left-join


    【解决方案1】:

    看起来您可以使用“ANY”子查询 http://dev.mysql.com/doc/refman/5.0/en/any-in-some-subqueries.html

    SELECT
        n.*,
        MIN(n.state) state,
        MIN(n.status) status,
        MAX(n.date) maxDate
    FROM notifications n
    WHERE n.toID = '$session' AND
        (
            (
                n.type = 'likes' AND
                n.uniqueID = ANY (
                    SELECT likes.id
                    FROM likes INNER JOIN posts on (likes.postId=posts.id)
                    WHERE likes.state='0' and posts.state='0'
                )
            ) OR
            (
                n.type = 'comment' AND
                n.uniqueID = ANY (
                    SELECT comments.id
                    FROM comments INNER JOIN posts on (comments.postId=posts.id)
                    WHERE comments.state='0' and posts.state='0'
                )
            ) OR
            (
                n.type = 'post' AND
                n.uniqueID = ANY (SELECT id FROM posts WHERE state='0')
            )
        )
    GROUP BY n.uniqueID
    ORDER BY status ASC, maxDate DESC;
    

    【讨论】:

    • 哦,非常感谢!到目前为止,这似乎工作正常,我将继续测试一切以确保它是,但这绝对是我一直在寻找的!
    • 我发现了一件事。对于这3种特定的通知类型,如果帖子的状态不等于0,那么它不应该显示该通知。所以如果有点赞,并且评论了ID为36的帖子,只要帖子的状态(在posts表中)为0,它就必须显示,但是如果状态更改为,在这种情况下, 1,它不应该显示该帖子的评论或喜欢通知。在 cmets 和 likes 表中,我有一个名为“postID”的列,因此例如,n.type='comment' 之一,还应该检查帖子表并找到具有该 ID 的帖子以确保状态为 0,对于喜欢
    • 所以“状态”是帖子的一部分,而不是喜欢/cmets 表?如果是这样,可以将“喜欢”子查询更改为(SELECT likes.id FROM likes INNER JOIN posts on (likes.postId=posts.id) where posts.state='0')
    • 好吧,“状态”是每个表的一部分,因此必须对每个表进行检查,因为对于任何通知类型,状态都可以从 0 变为 1,所以你有它现在绝对是它需要检查的方式,但是,除了那些,对于喜欢和 cmets 类型的,它还必须检查帖子表,因为如果帖子已被删除(状态从 0 变为 1),不应显示这些通知。但是,我将添加不会直接归因于帖子表的通知类型,所以它...
    • 不能真正对整个查询进行绝对检查,但就像您现在的情况一样,基于每种类型。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-07
    • 1970-01-01
    • 2020-03-28
    相关资源
    最近更新 更多