MySQL-如何比较查询结果的顺序是否与另一个顺序相同?

时间:2018-07-05 07:35:18

标签: mysql sql database

想象一下,我有一个名为 Log 的数据库表,看起来像这样:

+----+---------+---------+
| id | item_id | message |
+----+---------+---------+
| 1  |    1    |    A    |
+----+---------+---------+
| 2  |    1    |    B    |
+----+---------+---------+
| 3  |    1    |    C    |
+----+---------+---------+
| 4  |    2    |    A    |
+----+---------+---------+
| 5  |    2    |    C    |
+----+---------+---------+
| 6  |    2    |    B    |
+----+---------+---------+
| 7  |    3    |    B    |
+----+---------+---------+
| 8  |    3    |    A    |
+----+---------+---------+
| 9  |    3    |    C    |
+----+---------+---------+

如果我查询

select * from log where item_id = 1 order by id;

我将收到第1、2和3行。与我查询的情况相同

select * from log where item_id = 1 order by message;

但是,如果我对项目2相同,则订单将有所不同。按ID排序,行的顺序为4、5和6,但按消息的顺序为4、6和5。

这是我的问题,是否可以通过查询来了解哪个item_ids与两个查询相比具有不同的顺序?

在此示例中,结果将是项目2和3。

2 个答案:

答案 0 :(得分:2)

如果我理解正确,则可以使用group_concat()

select l.item_id,
       group_concat(l.id order by l.id) as id_ordering,
       group_concat(l.id order by l.message) as message_ordering
from log l
group by l.item_id;

您可以使用having子句来获得不同的内容:

select l.item_id,
       group_concat(l.id order by l.id) as id_ordering,
       group_concat(l.id order by l.message) as message_ordering
from log l
group by l.item_id
having id_ordering <> message_ordering;

答案 1 :(得分:0)

您可以使用变量来解决此问题,这是一个间隙和孤岛问题。

以下查询:

SELECT id, item_id, message, id - seq
FROM (
  SELECT id, item_id, message,
         @seq := IF(@i = item_id, @seq + 1, 
                    IF(@i := item_id, 1, 1)) AS seq       
  FROM log
  CROSS JOIN (SELECT @i := 0, @seq := 0) AS v
  ORDER BY item_id, message) AS t
ORDER BY id;

生成此输出:

id, item_id, message, id - seq
--------------------------------
1,  1,       A,       0
2,  1,       B,       0
3,  1,       C,       0
4,  2,       A,       3
5,  2,       C,       2
6,  2,       B,       4
7,  3,       B,       5
8,  3,       A,       7
9,  3,       C,       6

因此可以使用id-seq来检测idmessage之间的顺序不匹配:

SELECT item_id
FROM (
  SELECT id, item_id, message,
         @seq := IF(@i = item_id, @seq + 1, 
                    IF(@i := item_id, 1, 1)) AS seq       
  FROM log
  CROSS JOIN (SELECT @i := 0, @seq := 0) AS v
  ORDER BY item_id, message) AS t
GROUP BY item_id
HAVING COUNT(DISTINCT id-seq) > 1  
ORDER BY id;

Demo here