如果记录重复,我有一个表格,其中填充了一个字段。该代码已经在运行,并正确检查重复项并且正在运行。
该表如下所示:
id | dupe_ids | id_subscription
1 NULL 5343
2 3, 4 5343
3 2, 4 5343
4 2, 3 5343
5 NULL 5343
6 7 5343
7 6 5343
查询应返回条目数的计数,但需要对重复的 id 进行分组。我需要查询将具有条目的记录分组为一个计数,但以某种方式基于重复项。在上面的示例中,订阅 5343 的计数为 4。记录 2 将计为 1,其中 3 和 4 被跳过或分组,记录 6 将计为 1,记录 7 被分组或跳过。
查询现在如下所示:
SELECT app.id_subscription, app.id_site, app.id_customer, COUNT(*) AS app_count, site.url
FROM web_manager.app, web_manager.site
WHERE app.id_customer = :wm_id
AND (app.received_at BETWEEN :sdate AND :edate)
AND app.id_site = site.id
AND app.dupe_ids IS NULL
GROUP BY app.id_subscription
ORDER BY app_count DESC
最佳答案
如果 dupe_ids
中的值是一个数字列表 id
值,并且列表始终“按顺序”排列,最低值是列表中的第一个,作为一个肮脏的解决方案......
我的原始答案(如下)中的查询已修改为替换常量 0
用这样的表达式:LEAST(a.id,SUBSTRING_INDEX(a.dupe_ids,',',1)+0)
.
该表达式的意思是:从 dupe_ids
中获取第一个值列表,在数字上下文中对其进行评估,将数值与 id
进行比较行中的值,并返回两者中的较低值。
SELECT COUNT(DISTINCT IF(a.dupe_ids IS NULL,a.id,LEAST(a.id,SUBSTRING_INDEX(a.dupe_ids,',',1)+0))) AS my_funky_cnt
, a.id_subscription
FROM web_manager.app a
JOIN web_manager.site s
ON s.id = a.id_site
WHERE ...
GROUP BY a.id_subscription
按 my_funky_cnt DESC 排序
同样,删除
GROUP BY
和聚合,以查看表达式实际返回的内容... SELECT a.id
, a.dupe_ids
, a.id_subscription
, IF(a.dupe_ids IS NULL,a.id,LEAST(a.id,SUBSTRING_INDEX(a.dupe_ids,',',1)+0)) AS expr
FROM web_manager.app a
JOIN web_manager.site s
ON s.id = a.id_site
WHERE ...
ORDER BY a.id_subscription, a.dupe_ids IS NULL, a.id
我们希望它会返回:
id | dupe_ids | id_subscription | expr
2 3, 4 5343 2 -- id=2 is less than fv=3
3 2, 4 5343 2 -- fv=2 is less than id=3
4 2, 3 5343 2 -- fv=2 is less than id=4
6 7 5343 6 -- id=6 is less than fv=7
7 6 5343 6 -- fv=6 is less than id=7
1 NULL 5343 1
5 NULL 5343 5
所以一个
GROUP BY id_subscription
和 COUNT(DISTINCT expr)
将返回计数 4。(这未经测试)
这种方法取决于
dupes_id
首先列出最低的 id 值(列表中的第一个值),在数字上下文中评估第一个值,并将其与 id
进行比较行中的值。如果
dupe_ids
是空字符串,或者以逗号开头,或者第一个非空白字符不能解释为数值,则 expr
将返回 0
.编辑
原始答案(如下)是基于折叠给定 id_subscription 的所有具有非 NULL 值的行...返回计数 3。问题已更新,添加了更多不应该具有非 NULL 值的示例行一起坍塌。 “count”的期望返回现在是 4。原始答案中的查询将返回 3。
获取 NULL 值为
dupe_ids
的行数很简单。粘性 wicket 是
dupe_ids
的奇怪内容列,逗号分隔的 id 值列表... id dupe_ids
---- --------
2 '3,4'
3 '2,4'
4 '2,3'
6 '7'
7 '6'
如果我们不处理值的“逗号分隔列表”,这会更容易。如果我们改为在单独的表中对行进行外键引用。或者,如果我们有除
dupe_ids
之外的其他标准列来识别“重复”的行。但是,这不是被问到的问题。这个问题没有问是否最好避免存储逗号分隔的列表;是否有更好的方法。
这个问题让我们处理一个逗号分隔的列表。 (这是我们强烈建议首先避免使用逗号分隔列表的一个例子)。
如果我们有一个具有
dupe_ids
中的值的表达式连同 id
值,一起,以便我们在行上具有相同的值......id dupe_ids expr
---- -------- ------
2 '3,4' '2,3,4'
3 '2,4' '2,3,4'
4 '2,3' '2,3,4'
6 '7' '6,7'
7 '6' '6,7'
然后我们可以使用
COUNT(DISTINCT expr)
让我们得到我们所追求的返回。丑陋的部分是获得 expr
的值.在前面添加或附加 id
很容易转至 dupe_ids
,但生成的字符串值不会相同。列表将按不同的顺序排列。MySQL 中没有简单的内置函数来返回
expr
显示的值。基于id
的内容和 dupe_ids
.原始答案
我会采取的方法是使用一个表达式,并计算它的不同值。
如果
dupe_ids
为 null,则返回唯一值。如果 id
在表中是唯一的,我只会使用该列的值。如果 dupe_ids
不为空,然后替换一个无效的常量id
值(value)。假设 id
值是正整数,我会使用 0 或负值。举个例子:
SELECT COUNT(DISTINCT IF(a.dupe_ids IS NULL,a.id,0)) AS my_funky_cnt
, a.id_subscription
FROM web_manager.app a
JOIN web_manager.site s
ON s.id = a.id_site
WHERE ...
GROUP BY a.id_subscription
ORDER BY my_funky_cnt DESC
我会通过首先在没有 GROUP BY 和聚合的情况下进行查询来验证表达式是否“有效”...
SELECT a.id
, a.dupe_ids
, a.id_subscription
, IF(a.dupe_ids IS NULL,a.id,0) AS derived_col
FROM web_manager.app a
JOIN web_manager.site s
ON s.id = a.id_site
WHERE ...
ORDER BY a.id_subscription, a.dupe_ids IS NULL, a.id
我们希望它会返回:
id | dupe_ids | id_subscription | derived_col
1 NULL 5343 1
2 3, 4 5343 0
3 2, 4 5343 0
4 2, 3 5343 0
5 NULL 5343 5
所以所有非空行
dupe_ids
具有相同的值,并且具有 NULL dupe_ids
的行有独特的值(value)。还有一个
COUNT(DISTINCT
该表达式将返回 3。
关于MYSQL 按不为空的字段分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39967207/