从大型mysql数据集中找出UIDS,其中数据未更改'n'次

时间:2019-05-12 19:06:44

标签: mysql sql

我有一张下表,

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。

1 个答案:

答案 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即可得到计数。

db<>fiddle