[英]group by and count within a subquery
我正在嘗試使用從(users_status表)中的數據派生的條件來過濾掉(users表)數據。
users表是包含用戶標識和用戶名的表
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(25),
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
組表是包含組ID的表
CREATE TABLE `groups` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(25),
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
user_status表是一個包含活動日志的表。 它的工作方式是當用戶在組中時 ,用戶可以在“打開”或“關閉”之間切換“已標記”。
CREATE TABLE `user_status` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`group_id` int(10) unsigned,
`user_id` int(10) unsigned,
`bookmarked` enum('on', 'off'),
`date` datetime,
PRIMARY KEY (`id`),
CONSTRAINT `group_id` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE,
CONSTRAINT `user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
現在,我正在嘗試檢索所有在user_status中沒有條目或在user_status中的最后一個條目為“ off”的用戶。
我有一個SQL小提琴,其中有一個不完整的子查詢,我嘗試在其中執行此操作,但是卻無法正常工作。 http://sqlfiddle.com/#!2/2d5b4/2
select us.id, us.group_id, g.name as GROUP_NAME, us.user_id, u.username as USER_USERNAME, us.bookmarked, us.date
from user_status us
inner join users u ON u.id = us.user_id
inner join groups g ON g.id = us.group_id
where 'on' != (
select bookmarked
from user_status
group by (group_id, user_id)
where group_id = us.group_id AND user_id = us.user_id
order by ID DESC
limit 1;
);
編輯6:28 pm所以給定user_status
select * from user_status order by group_id, user_id, date;
+----+----------+---------+------------+--------------------------------+
| ID | GROUP_ID | USER_ID | BOOKMARKED | DATE |
+----+----------+---------+------------+--------------------------------+
| 1 | 1 | 1 | on | January, 16 2014 00:00:00+0000 |
| 2 | 1 | 1 | off | January, 17 2014 00:00:00+0000 |
| 3 | 1 | 1 | on | January, 18 2014 00:00:00+0000 |
| 9 | 1 | 1 | on | January, 18 2014 00:00:00+0000 |
| 7 | 1 | 2 | on | January, 16 2014 00:00:00+0000 |
| 8 | 1 | 2 | off | January, 17 2014 00:00:00+0000 |
| 4 | 2 | 1 | on | January, 16 2013 00:00:00+0000 |
| 5 | 2 | 1 | off | January, 17 2013 00:00:00+0000 |
| 6 | 2 | 1 | on | January, 18 2013 00:00:00+0000 |
+----+----------+---------+------------+--------------------------------+
我希望
group_id(1)user_id(1) 未返回,因為最后一個標記為“ on”
GROUP_ID(1)的user_id(2) 返回 ,因為最后一個書簽是'斷開'
group_id(2)user_id(1) 未返回,因為上一個標記為“ on”
由於user_status中不存在user_id(3)而返回注:在原始sql小提琴示例中未添加user_id 3
1-您在WHERE
子句之前使用group by
2-您在子查詢中按兩列分組,而您應按一列分組
試試這個工作查詢
select us.id, us.group_id, g.name as GROUP_NAME, us.user_id, u.username as USER_USERNAME, us.bookmarked, us.date
from user_status us
inner join users u ON u.id = us.user_id
inner join groups g ON g.id = us.group_id
where 'on' != (
select bookmarked
from user_status
where group_id = us.group_id AND user_id = us.user_id
group by (group_id) --->// you can choose to group by user_id or this.
order by ID DESC
limit 1
);
我會嘗試過濾聯接,因為這比具有大數據集的子查詢要好得多:
SELECT DISTINCT
groups.id AS groupid,
users.id AS userid,
groups.name AS groupname
FROM user_status
INNER JOIN users ON user_status.user_id=users.id
INNER JOIN groups ON user_status.group_id=groups.id
LEFT JOIN
(SELECT
user_id,
group_id,
MAX(`date`) AS maxondate
FROM user_status
WHERE bookmarked='on'
GROUP BY user_id, group_id
) AS ondate ON ondate.group_id=groups.id AND ondate.user_id=users.id
LEFT JOIN
(SELECT
user_id,
group_id,
MAX(`date`) AS maxoffdate
FROM user_status
WHERE bookmarked='off'
GROUP BY user_id, group_id
) AS offdate ON offdate.group_id=groups.id AND offdate.user_id=users.id
WHERE
maxondate IS NULL
OR (
maxondate IS NOT NULL
AND maxoffdate IS NOT NULL
AND maxondate<maxoffdate
)
試試這個例子sqlfiddle :
SELECT us.id, us.group_id, g.name AS GROUP_NAME, u.id AS user_id, u.username AS USER_USERNAME, us.bookmarked, us.date
FROM users u
LEFT OUTER JOIN user_status us ON u.id = us.user_id AND us.bookmarked = 'off'
LEFT OUTER JOIN groups g ON g.id = us.group_id
WHERE us.date = (SELECT max(ss.date) FROM user_status ss WHERE ss.user_id = us.user_id)
OR NOT EXISTS (SELECT 1 FROM user_status ss WHERE ss.user_id = u.id)
以下假設用戶可以同時對不同的組具有不同的書簽狀態。
它找到每個(user_id,group_id)組合的最新日期,然后找到與其對應的記錄。
如WHERE
子句所示,書簽需要為'off'
或NULL
。
由於使用了LEFT JOIN
,有可能返回user_group
沒有記錄的用戶。
SELECT
u.*,
g.*,
us.*
FROM
users AS u
LEFT JOIN
(
SELECT user_id, group_id, MAX(date) AS date
FROM user_status
GROUP BY user_id, group_id
)
AS us_newest
ON us_newest.user_id = u.id
LEFT JOIN
user_status AS us
ON us.user_id = us_newest.user_id
AND us.group_id = us_newest.group_id
AND us.date = us_newest.date
LEFT JOIN
groups AS g
ON g.id = us.group_id
WHERE
us.bookmarked = 'off'
OR us.bookmarked IS NULL
;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.