【问题标题】:Other function like FIND_IN_SET which returns number of strings available in comma separated list其他函数,如 FIND_IN_SET,它返回逗号分隔列表中可用的字符串数
【发布时间】:2020-01-01 06:17:54
【问题描述】:

根据官方文档,FIND_IN_SET 返回逗号分隔列表中第一次出现的可用字符串的位置。但我想获取逗号分隔列表中可用字符串的计数。

例如:

SELECT id, name, FIND_IN_SET(id, '1,1,2,3,4,4,5,6,7,7,7') as num FROM users;

返回如下结果

+----+---------------+
| id | name    | num |
+----+---------------+
|  1 | Jack    |   1 |
|  2 | Alex    |   3 |
|  3 | John    |   4 |
|  4 | Brett   |   5 |
|  5 | Keith   |   7 |
|  6 | Richard |   8 |
|  7 | Kent    |   9 |
+----+---------------+

SQL 小提琴:http://sqlfiddle.com/#!9/9eeacb/2

但我想要与表的 id 匹配的 id 计数。因此,预期的输出应该如下所示。

SELECT id, name, SOME_FUNCTION(id, '1,1,2,3,4,4,5,6,7,7,7') as num FROM users;

    +----+---------------+
    | id | name    | num |
    +----+---------------+
    |  1 | Jack    |   2 |
    |  2 | Alex    |   1 |
    |  3 | John    |   1 |
    |  4 | Brett   |   2 |
    |  5 | Keith   |   1 |
    |  6 | Richard |   1 |
    |  7 | Kent    |   3 |
    +----+---------------+

【问题讨论】:

  • 如何生成逗号分隔的id 值列表?
  • 这是 PHP 变量以编程方式出现。
  • 那么为什么不在 PHP 中使用 array_count_values 计算呢?
  • 我不想遍历所有记录。这只是一个有 5-7 条记录的示例。我在数据库中有 1000 多条记录
  • 我还是不明白为什么你不能只计算 PHP 中字符串中的值。你能举一个更详细的例子来说明你想要实现的目标吗?

标签: mysql sql


【解决方案1】:

使用字符串函数技巧:

set @s = '1,1,2,3,4,4,5,6,7,7,7';
select id, name,
  ceiling((length(@s) - length(trim(both ',' from replace(
    replace(concat(',', replace(@s, ',', ',,'), ','), concat(',', id, ',' ), ''),
    ',,', ','
  )))) / (length(id) + 1)) as num
from users

请参阅demo(以及其他可能的情况)。
结果:

id | name    | num
 1 | Jack    | 2
 2 | Alex    | 1
 3 | John    | 1
 4 | Brett   | 2
 5 | Keith   | 1
 6 | Richard | 1
 7 | Kent    | 3

【讨论】:

    【解决方案2】:

    最好的答案是摆脱 CSV 范式,而是让 ids 的集合匹配到自己的表中:

    CREATE TABLE ids (id int);
    INSERT INTO ids (id)
    VALUES (1),(1),(2),(3),(4),(4),(5),(6),(7),(7),(7);
    

    然后使用以下简单查询:

    SELECT
        u.id,
        u.name,
        COUNT(i.id) AS num
    FROM users u
    LEFT JOIN ids i
        ON u.id = i.id
    GROUP BY
        u.id,
        u.name;
    

    【讨论】:

    • 这可能是解决方案,但这些 id 以编程方式来自 PHP 变量。我无法创建表格。
    • 那么您可能需要查询users 并针对每条记录确定与您的CSV 字符串的重叠计数。
    • 你的意思是遍历每个用户记录吗?
    • @VivekPipaliya 您能否使用相关的 PHP 代码编辑您的问题,以便我们帮助您找到解决方案。
    • 如果不使用我的答案或编写存储过程,您将无法在 MySQL 中轻松做到这一点。所以,用 PHP 处理可能是你最好的选择。
    【解决方案3】:

    您将比较值作为字符串传递。你可以做一些字符串技巧来计算字符串中值的数量,然后将其相加:

    SELECT u.id, u.name,
           COUNT(*),
           SUM( (LENGTH(REPLACE(CONCAT(',', ids, ','), u.id, CONCAT(u.id, 'X'))) -
                 LENGTH(CONCAT(',', ids, ','))
                ) 
              )
    FROM users u CROSS JOIN
         (SELECT '1,1,2,3,4,4,5,6,7,7,7' as ids) x
    WHERE FIND_IN_SET(u.id, x.ids) > 0
    GROUP BY u.id, u.name;
    

    注意:我创建子查询x是为了方便,所以可以参考ids。您可以将值作为参数传递:

    SELECT u.id, u.name,
           COUNT(*),
           SUM( (LENGTH(REPLACE(CONCAT(',', ?, ','), u.id, CONCAT(u.id, 'X'))) -
                 LENGTH(CONCAT(',', ?, ','))
                ) 
              )
    FROM users u 
    WHERE FIND_IN_SET(u.id, ?) > 0
    GROUP BY u.id, u.name;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-22
      • 2014-03-16
      • 2013-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多