简体   繁体   English

简化MYSQL查询并修复

[英]simplifying a MYSQL query, and fixing

I've been trying to get this complex MYSQL query to work exactly right over the last few days, of course because it's got so many aspects to it that effect it it's difficult to surely know that it's 100% working correctly, and I'm not at all good with more complex MYSQL queries. 我一直在尝试使这种复杂的 MYSQL查询在过去几天中完全正确地工作,当然,因为它涉及到很多方面,因此很难确定它是否100%正确地工作,我是较复杂的MYSQL查询一点也不好。 also this query that I have now is quite messy, so the data it returns is a little scattered, and I'm not exactly sure how to address this issue. 我现在遇到的这个查询也很混乱,因此返回的数据有点分散,我不确定如何解决此问题。 I've read through MYSQL Join and everything and I sort of understand it, but I'm not sure which to use in my case, and how to use them properly. 我已经阅读了MYSQL Join和所有内容,并且对它有所了解,但是我不确定在我的情况下使用哪个以及如何正确使用它们。

Here's my current query that works as it should. 这是我当前的查询,它可以正常工作。 (just needs cleaning up, I think, so I don't have to have redundant values) (我认为只是需要清理,因此我不必具有多余的值)

$notificationsq = mysql_query("SELECT
N.*,
N.fromID,
N.date,
N.id AS ID,   //I have to do this because if I don't it doesn't return anything, 
              ///I guess because it joins 3 tables with the id column. not sure 
              ///how to call the correct data.
MIN(N.state) AS State,
MAX(N.date) AS newDate,
P.*,
C.*,
P.id AS uniqueID
FROM notifications N
LEFT JOIN comments C ON N.action = 2 AND N.uniqueID = C.id AND C.state=0
LEFT JOIN posts P ON N.action = 1 AND P.id = N.uniqueID 
OR N.action = 2 AND P.id = C.postID
WHERE N.userID = '$session'
AND (N.action = 1 AND N.state IN (0, 1) OR N.action = 2)
AND P.state = 0

GROUP BY P.id
ORDER BY
State ASC,  
newDate DESC


 ") or die(mysql_error());

My table structure: 我的表结构:

Table: notifications

id  UserID  FromID  UniqueID    Action  State   Read_Date   Date
1   1       2       1           1       0       0           1325993600
2   1       6       2           1       0       0           1325993615
3   1       2       1           2       0       0           1325993622
4   1       6       2           2       0       0           1325993661
5   2       6       2           2       0       0           1325993661

Action = 1 means UniqueID identifies a column in Posts; 动作= 1表示UniqueID标识帖子中的一列; Action = 2 means UniqueID identifies a column in Comments. 动作= 2表示UniqueID标识“注释”中的一列。

Table: posts

id  ToID    FromID  Post        State   Date
1   1       2       Hey         0       1325993600
2   1       6       okay yeah   0       1325993615

Table: comments

ID  PostID  FromID  Comment     State   Date
1   1       2       lol         0       1325993622
2   1       6       ohh         0       1325993661

So, in the Notifications table where action is 2, the UniqueID's are for the 'id' in the Comments table. 因此,在actions为2的Notifications表中,UniqueID是Comments表中的“ id”。 What I want to return is the PostID, so in the query it would just be as if the UniqueID was this instead: 我要返回的是PostID,因此在查询中就好像UniqueID是这样:

1
2
1
1
1

If your state = 0 filter limits the connection to the comments, then the inner join on the posts could filter out the result, try making that a left join as well to test. 如果您的状态= 0过滤器将连接限制为注释,则帖子中的内部联接可能会过滤掉结果,并尝试使该联接成为左联接以进行测试。

You should have a prefix on your ORDER BY clause (either ORDER BY P.State or N.State). 您的ORDER BY子句上应该有一个前缀(ORDER BY P.State或N.State)。

The reason you're having an error with the N.id is that the id is already selected with the N.* 您在使用N.id时出错的原因是该ID已被N. *选择。

You're better to use an ENUM type to deal with multiple states. 最好使用ENUM类型来处理多个状态。 This leads to more readable SQL with the same performance (ie. N.action = 'add', instead of 2) 这导致具有相同性能的更具可读性的SQL(即N.action ='add',而不是2)

Avoid any select *, it's error prone and the performance isn't as good as the manual alternative. 避免使用任何选择*,因为它容易出错,并且性能不如手动选择好。

As far as cleaning up, I find it much easier to read with clean whitespace and names: 至于清理,我发现使用干净的空格和名称更容易阅读:

SELECT notifications.*
     , notifications.fromID
     , notifications.date
     , MIN(notifications.state) AS State
     , MAX(notifications.date) AS newDate
     , posts.*
     , comments.*
     , posts.id AS uniqueID
FROM notifications
LEFT JOIN comments ON notifications.action = 2
                  AND notifications.uniqueID = C.id
                  AND comments.state = 0
LEFT JOIN posts ON (notifications.action = 1 AND posts.id = notifications.uniqueID)
                OR (notifications.action = 2 AND posts.id = comments.postID)
WHERE notifications.userID = '$session'
  AND (notifications.action = 1 AND notifications.state IN (0, 1) OR notifications.action = 2)
  AND posts.state = 0
GROUP BY posts.id
ORDER BY notifications.State ASC
       , newDate DESC

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM