首页 > 解决方案 > 如何在整个子查询中使用 group_concat?

问题描述

...无需进行不必要的比较

我想获得一系列行的 md5 哈希。由于带宽限制,我希望它发生在服务器端。

这有效:

create table some_table (id int auto_increment,
                         col1 varchar(1),
                         col2 int,
                         primary key (id));

insert into some_table (col1, col2)
                values ('a', 1),
                       ('b', 11),
                       ('c', 12),
                       ('d', 25),
                       ('e', 50);

select group_concat(id,col1,col2) from
    (select * from some_table
     where id >= 2 and id < 5
     order by id desc) as some_table
group by 1 = 1;

输出:

+----------------------------+
| group_concat(id,col1,col2) |
+----------------------------+
| 2b11,3c12,4d25             |
+----------------------------+

并使用哈希:

select md5(group_concat(id,col1,col2)) from
    (select * from some_table
     where id >= 2 and id < 5
     order by id desc) as some_table
group by 1 = 1;

输出:

+----------------------------------+
| md5(group_concat(id,col1,col2))  |
+----------------------------------+
| 32c1f1dd34d3ebd33ca7d95f3411888e |
+----------------------------------+

但我觉得应该有更好的方法。

特别是,我想避免将 1 与 1 百万次进行比较,这是我发现将行范围放入一个组所必需的,我需要它才能使用group_concat,我需要它才能md5在多行上使用。

有没有一种方法可以group_concat在行范围内使用(或类似的),而无需进行不必要的比较?

编辑

我想对多行进行哈希处理,以便可以比较不同服务器上生成的哈希值。如果它们不同,我可以得出结论,子查询返回的行存在差异。

标签: pythonmysql

解决方案


解决方案就是完全省略group by 1 = 1。我曾假设这group_concat需要我为其提供一个组,但它可以直接用于子查询,如下所示:

select group_concat(id,col1,col2) from
    (select * from some_table
     where id >= 2 and id < 5
     order by id desc) as some_table;

请注意,空值需要转换为对 concat 友好的值,如下所示:

insert into some_table (col1, col2)
                values ('a', 1),
                       ('b', 11),
                       ('c', NULL),
                       ('d', 25),
                       ('e', 50);

select group_concat(id, col1, col2) from
    (select id, col1, ifnull(col2, 'NULL') as col2
     from some_table
     where id >= 2 and id < 5
     order by id desc) as some_table;

输出:

+------------------------------+
| group_concat(id, col1, col2) |
+------------------------------+
| 2b11,3cNULL,4d25             |
+------------------------------+

group_concat另一个警告:mysql 有一个由变量定义的最大长度: group_concat_max_len. 为了散列n表行的串联,我需要:

  1. 散列行,使其以 32 位表示,无论它有多少列
  2. 确保group_concat_max_len > (n * 33)(额外的字节用于添加逗号)
  3. 散列group_concat散列的行。

最终,我最终使用客户端语言来检查每列的名称、编号和可空性,然后构建如下查询:

select md5(group_concat(row_fingerprint)) from
    (select concat(id, col1, ifnull(col2, 'null')) as row_fingerprint
     from some_table
     where id >= 2 and id < 5
     order by id desc) as foo;

有关更多详细信息,您可以在此处查看我的代码(请参阅函数:find_diff_intervals)。


推荐阅读