选择基于不同的列中的唯一GROUP_CONCAT-ED行

时间:2019-02-02 22:24:23

标签: mysql sql group-by unique-key

给定表可以包含以下行。

即对于给定的filename,可以有两个独特的version_id(一个或多个)。

file_id    version_id      filename
1          OS_v1           abc.update
1          App_v1          abc.update
2          OS_v2           xyz.update
2          App_v2          xyz.update
3          OS_v1           abc(1).update
3          App_v1          abc(1).update

PRIMARY KEY (`version_id`, `filename`)

如何检测没有两个不同的文件名具有相同的OS_App(版本)组合?

在给定的示例中,用file_id=3设置的行是file_id=1的副本。

注意:为OS和App版本定义单独的列很容易,但是这需要大量代码更改,而我们不希望这样做。

问题:是否有一个SELECT查询将仅返回file_id = 1file_id = 2并省略file_id = 3

到目前为止,我想出了这个查询,该查询选择了version_id分组的filename的组合,但第2行与第1行重复

SELECT   DISTINCT(GROUP_CONCAT(version_id SEPARATOR '-')) ,
         filename
FROM     schema_name.table_name
GROUP BY filename;

返回:

concat_version patch_filename
OS_V1-APP_V1   xyz.update
OS_V2-APP_V2   abc(1).update
OS_V1-APP_V1   abc.update

1 个答案:

答案 0 :(得分:1)

  

问题:是否存在SELECT查询,该查询仅返回file_id = 1和file_id = 2并省略file_id = 3

如果您使用的是MySQL 8.0,则可以利用窗口函数ROW_NUMBER()

SELECT x.file_id, x.version_id, x.filename
FROM (
    SELECT t.*, ROW_NUMBER() OVER(PARTITION BY version_id ORDER BY file_id) rn
    FROM master_logs.system_patches t    
) x
WHERE x.rn = 1

内部查询为version_id组中的每个记录分配一个行号,按file_id排序,外部查询对行号为1的记录进行过滤。


在MySQL的早期版本中,一种典型的解决方案是使用具有NOT EXISTS条件的相关子查询来过滤掉不需要的记录:

SELECT t.file_id, t.version_id, t.filename
FROM master_logs.system_patches t 
WHERE NOT EXISTS (
    SELECT 1 
    FROM master_logs.system_patches t1
    WHERE t1.version_id = t.version_id AND t1.file_id < t.file_id
)