SQL FIDDLE:http://sqlfiddle.com/#!2/5895f/5
我有群组,每个群组( item_group )可以包含多个项目(项目),每个项目每个用户都有一个状态条目( item_status )。 我正在尝试检索不属于您自己的每个组的最后一项。可以把它想象成一个消息线程,你只想看到该线程的预览是发送的最后一条消息,但不是你的消息。
这适用于我的查询
SELECT * FROM (
SELECT it.id as group_id, i.sender_id as sender_id
FROM item_group it
JOIN item i ON (i.item_group_id = it.id)
JOIN item_status s ON (s.item_id = i.id)
) as results
WHERE results.sender_id != 2
GROUP BY results.group_id;
然而,下一步是我想确保我的项目的任何项目的状态不是0这是我的问题所在。它表示未知列'results.group_id'
SELECT * FROM (
SELECT it.id as group_id, i.sender_id as sender_id
FROM item_group it
JOIN item i ON (i.item_group_id = it.id)
JOIN item_status s ON (s.item_id = i.id)
) as results
WHERE results.sender_id != 2
AND (SELECT COUNT(*) = 0
FROM item_status s
--- PROBLEM IS HERE results.group_id ---
JOIN item i ON (i.item_group_id = results.group_id AND s.item_id = i.id)
----------------------------------------
WHERE s.user_id = 2 AND s.status = 0)
GROUP BY results.group_id;
CREATE TABLE item_group (
id int(10) PRIMARY KEY NOT NULL AUTO_INCREMENT);
CREATE TABLE item (
id int(10) PRIMARY KEY NOT NULL AUTO_INCREMENT,
item_group_id int(10) NOT NULL,
sender_id MEDIUMINT UNSIGNED NOT NULL);
CREATE TABLE item_status (
item_id int(10) NOT NULL,
user_id MEDIUMINT UNSIGNED NOT NULL,
status int(10) NOT NULL);
INSERT INTO item_group (ID) VALUES (1);
INSERT INTO item (item_group_id, sender_id) VALUES (1, 1);
INSERT INTO item (item_group_id, sender_id) VALUES (1, 2);
INSERT INTO item_status (item_id, user_id, status) VALUES (1, 1, 1);
INSERT INTO item_status (item_id, user_id, status) VALUES (1, 2, 1);
INSERT INTO item_status (item_id, user_id, status) VALUES (2, 1, 1);
INSERT INTO item_status (item_id, user_id, status) VALUES (2, 2, 1);
答案 0 :(得分:3)
我会用以下方式写这个,没有子查询:
SELECT i.item_group_id as group_id, i.sender_id as sender_id
FROM item i
JOIN item_status s ON (s.item_id = i.id)
LEFT OUTER JOIN (
item i2 INNER JOIN item_status s2
ON (s2.item_id = i2.id AND s2.user_id = 2 AND s2.status = 0)
) ON (i.item_group_id = i2.item_group_id)
WHERE i.sender_id != 2 AND i2.item_group_id IS NULL
GROUP BY group_id ORDER BY NULL;
您还应该创建以下索引:
ALTER TABLE item_status
ADD KEY (user_id, status),
ADD KEY (item_id);
我在MySQL 5.5.30上测试了这个查询。使用推荐的索引,优化程序EXPLAIN报告如下:
+----+-------------+-------+--------+-----------------+---------+---------+-----------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-----------------+---------+---------+-----------------+------+----------------------------------------------+
| 1 | SIMPLE | i | ALL | PRIMARY | NULL | NULL | NULL | 2 | Using where; Using temporary |
| 1 | SIMPLE | s2 | ref | user_id,item_id | user_id | 7 | const,const | 0 | |
| 1 | SIMPLE | i2 | eq_ref | PRIMARY | PRIMARY | 4 | test.s2.item_id | 1 | Using where |
| 1 | SIMPLE | s | ref | item_id | item_id | 4 | test.i.id | 1 | Using index |
+----+-------------+-------+--------+-----------------+---------+---------+-----------------+------+----------------------------------------------+
我想到了一个针对您的后续问题的快速解决方案,如何获取所有项目的状态为0的项目组。
SELECT i.item_group_id as group_id, i.sender_id as sender_id
FROM item i
JOIN item_status s ON (s.item_id = i.id)
LEFT OUTER JOIN (
item i2 INNER JOIN item_status s2
ON (s2.item_id = i2.id AND s2.user_id = 2 AND s2.status <> 0)
) ON (i.item_group_id = i2.item_group_id)
WHERE i.sender_id != 2 AND i2.item_group_id IS NULL
GROUP BY group_id ORDER BY NULL;
除了我在连接条件中将= 0
更改为<> 0
之外,这与上述查询几乎完全相同。所以这意味着:
PS:我没有测试过这个,只是提供它作为快速解决方案。“尝试找到任何非零状态,如果找不到任何状态,那么OUTER JOIN将为连接表的所有列返回null。当发生这种情况时,你发现了一个包含所有列的项目组零状态。“