MYSQL 按不为空的字段分组

标签 mysql grouping

如果记录重复,我有一个表格,其中填充了一个字段。该代码已经在运行,并正确检查重复项并且正在运行。

该表如下所示:

 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_subscriptionCOUNT(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/

相关文章:

mysql - Rails form_用于设置选项和设置所选选项

mysql - 快速组 rank() 函数

python - 如何在 Pandas Dataframe 中的 groupby 之后使用 assign 函数

algorithm - 如何将集合中的结构化数据项合并成组?

kotlin - 按键列表分组( Kotlin )

python - 结合使用两个词典,其中之一优先:

php - 仅对选定值之一应用 where 子句

MySQL - 关于删除级联问题

mysql - 结合 JSON_SEARCH 和 JSON_EXTRACT 得到 : "Invalid JSON path expression."

php - 我怎样才能建立统计 map ?