我有一张下表,
id(Primary) uid data Time
1 1 20 2019-05-12 10:17:26
2 2 23 2019-05-12 10:17:26
3 3 45 2019-05-12 10:17:26
4 4 16 2019-05-12 10:17:26
5 2 23 2019-05-12 10:18:26
6 1 26 2019-05-12 10:18:26
7 4 15 2019-05-12 10:18:26
8 3 41 2019-05-12 10:18:26
9 4 15 2019-05-12 10:19:26
10 2 23 2019-05-12 10:19:26
11 3 38 2019-05-12 10:19:26
12 1 31 2019-05-12 10:19:26
13 3 48 2019-05-12 10:20:26
14 4 15 2019-05-12 10:20:26
15 1 19 2019-05-12 10:20:26
16 2 23 2019-05-12 10:20:26
17 1 22 2019-05-12 10:21:26
18 4 15 2019-05-12 10:21:26
19 2 23 2019-05-12 10:21:26
20 3 43 2019-05-12 10:21:26
我想找出唯一的UID,其中最新的“ n”个数据条目是相同的。在以上数据中,当n = 5时,我需要2作为结果。当n = 4时,我在结果集中需要2和4。
答案 0 :(得分:1)
一种简单的方法是使用ALL
和一个子查询,使用ORDER BY
获取最后一个 n (从现在开始让 n = 5)记录和LIMIT
。
SELECT *
FROM (SELECT DISTINCT
t1.uid
FROM elbat t1) x
WHERE (SELECT t2.data
FROM elbat t2
WHERE t2.uid = t1.uid
ORDER BY time DESC
LIMIT 1) = ALL (SELECT t3.data
FROM elbat t3
WHERE t3.uid = t1.uid
ORDER BY time DESC,
id DESC
LIMIT 5);
不幸的是,MySQL不允许子查询中限制为ALL
。
在MySQL 8中,我们可以通过在使用LIMIT
的子查询中添加另一个子查询来解决此问题。
SELECT *
FROM (SELECT DISTINCT
t1.uid
FROM elbat t1) x
WHERE (SELECT t2.data
FROM elbat t2
WHERE t2.uid = x.uid
ORDER BY time DESC
LIMIT 1) = ALL (SELECT x.data
FROM (SELECT t3.data
FROM elbat t3
WHERE t3.uid = x.uid
ORDER BY time DESC,
id DESC
LIMIT 5) x);
再次不幸的是,这在低于8的版本上将不起作用,因为外部查询的值不能在一个以上的级别上被引用,因此x.uid
在最内部的子查询中是未知的。
但是我们可以检查在另一个子查询中获得的以下行的计数,该计数小于5( n )。
SELECT *
FROM (SELECT DISTINCT
t1.uid
FROM elbat t1) x
WHERE (SELECT t2.data
FROM elbat t2
WHERE t2.uid = x.uid
ORDER BY time DESC
LIMIT 1) = ALL (SELECT t3.data
FROM elbat t3
WHERE t3.uid = x.uid
AND (SELECT count(*)
FROM elbat t4
WHERE t4.uid = t3.uid
AND (t4.time > t3.time
OR t4.time = t3.time
AND t4.id > t3.id)) < 5);
请注意,这还将返回uid
的结果,其中少于5( n )行,但所有行都等于data
。如果在这种情况下,您想排除各自的uid
,则需要添加另一个子查询,以获取uid
的最后一行的计数,并检查其是否大于或等于5( n )。只需将其中一个子查询带到ALL
,然后让它返回count(*)
而不是t3.data
即可得到计数。