我的问题可能与这些问题类似:
- MySQL group by with ordering/priority of another column
- Grouping by Column with Dependence on another Column
- MySQL GROUP BY with preference
表格示例:
source zip phone street city created_at
==================================================================
a 11111 11111 Flatlands null 2015-01-01
b 11111 11111 Flatlands Avenue New York 2015-01-01
c 11111 11111 Ave Flatlands New York 2015-01-01
a 22222 22222 Favory New York 2015-01-01
b 22222 22222 Favory Avenue New York 2017-12-12
c 22222 22222 Ave Favory New York 2015-01-01
b 33333 33333 Sixteenth Washington 2015-01-01
c 33333 33333 st. 16th null 2015-01-01
c 44444 44444 st. West Land null 2015-01-01
假设我有一张包含不同城市地点信息的表格。信息从 3 个不同的来源收集:a
、b
和 c
。
zip
和 phone
字段唯一标识位置,因此数据库中的行可以按这些字段分组。
我需要合并来自不同来源的不同位置的信息,根据 street
和 city
列的规则集选择最佳值。
规则是:
- 对于每个组,
street
和city
的非空值优先于 null 值。 - 在每个组中,
a
和b
来源的street
和city
列的值优先于c
source (weight(a
) = weight(b
) > weight(c
)) 如果这些列不为空。 - 对于源
a
和b
,优先考虑具有最新created_at
时间戳的行中的列值。
这是我想要收到的结果:
zip phone street city
====================================
11111 11111 Flatlands New York
22222 22222 Favory Avenue New York
33333 33333 Sixteenth Washington
44444 44444 st. West Land null
Here is a DB Fiddle to play with .
我不确定这是否可以通过 SQL 实现,也许我最好的选择是切换到 NoSQL DB + 命令式处理任务。或者只是使用一些工具从数据库中提取信息,然后对其进行处理。
附言这是一个简化的示例。
最佳答案
您可以使用以下查询来实现 street
的优先级规则:
SELECT zip, phone, street
FROM test
ORDER BY zip, phone,
-- prioritize non empty values over null values
CASE
WHEN (street IS NOT NULL) OR (street = '') THEN 0
ELSE 1
END,
-- prioritize a, b over c
CASE
WHEN source IN ('a', 'b') THEN 0
ELSE 1
END,
-- prioritize rows which have the latest created_at
created_at DESC
city
字段可以使用类似的查询。
然后你可以模拟 ROW_NUMBER
,不幸的是在 MySQL 中不可用,使用变量:
SELECT zip, phone, street,
@seq := IF(@id = CONCAT(zip,phone), @seq + 1,
IF(@id := CONCAT(zip,phone), 1, 1)) AS seq
FROM test
CROSS JOIN (SELECT @seq := 0, @id = '') AS v
ORDER BY zip, phone,
-- prioritize non empty values over null values
CASE
WHEN (street IS NOT NULL) OR (street = '') THEN 0
ELSE 1
END,
-- prioritize a, b over c
CASE
WHEN source IN ('a', 'b') THEN 0
ELSE 1
END,
-- prioritize rows which have the latest created_at
created_at DESC
同样,类似的查询可用于 city
字段。
通过在 zip
、street
和 seq = 1
上连接上述派生表,可以获得所需的结果。
关于MySQL group by 具有多个选择规则的多列的排序和优先级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46078468/