【问题标题】:How to count the number of occurrences of a attribute in a string of another table如何计算另一个表的字符串中某个属性的出现次数
【发布时间】:2021-02-20 06:44:33
【问题描述】:

我正在努力处理一个复杂的 SQL 查询,我想计算表 1 中的属性 x 在表 2 的字符串中出现的次数。 所以 t1 有一个 name 属性,t2 有一个参与者属性和一个 project 属性

ID | Name
---------
0  | Bob
1  | Bill
2  | Jill 

T2
Project | Participants
-----------------
0       | Bob, Bill
1       | Bob, Jill
2       | Bob

Output
Bob  3
Bill 1
Jill 1

t2 中的参与者是一个字符串。有没有办法做到这一点?

【问题讨论】:

  • 我建议将表 T2 设计为第一范式:link
  • 您正在苦苦挣扎,因为查询会很复杂,那是因为表 T2 不是第一范式。如果“Participants”字符串来自某个外部来源,那么您无法控制它——这很好,但它不应该以这种方式存储在关系数据库中,如 Oracle。字符串应该被分解成它的组件标记,结果就是应该存储的内容。事实上,在每个查询中,您都必须自己进行“标记化”(规范化),这很复杂,而且您会遇到困难。

标签: sql oracle csv count


【解决方案1】:

您应该主要专注于修复您的数据模型。每个项目的每个参与者都应存储为单独的行,而不是存储在分隔字符串中,可能通过外键约束引用另一个表:

project_id    participant_id
         0                 0   -- Bob
         0                 1   -- Bill
         1                 0   -- Bob
         1                 2   -- Jill
         2                 0   -- Bob

然后你可以有效地表达查询:

select t1.*
    (select count(*) from table2 t2 where t2.participant_id = t1.id) cnt
from table1 t1

也就是说,鉴于您当前的布局,一个选项使用字符串函数:

select t1.*, 
    (
        select count(*) 
        from table2 t2 
        where ', ' || t2.participants || ', ' like '%, ' || t1.name || ', %'
    ) cnt
from table1 t1

【讨论】:

    【解决方案2】:

    如果参与者在每个项目中只出现一次,那么您可以使用:

    SELECT t1.Name,
           COUNT( t2.Participants) AS cnt
    FROM   t1
           LEFT OUTER JOIN t2
           ON ( ', ' || t2.Participants || ', ' LIKE '%, ' || t1.Name || ', %' )
    GROUP BY t1.Name
    

    其中,对于样本数据:

    CREATE TABLE t1 ( ID, Name ) AS
    SELECT 0, 'Bob'  FROM DUAL UNION ALL
    SELECT 1, 'Bill' FROM DUAL UNION ALL
    SELECT 2, 'Jill' FROM DUAL UNION ALL
    SELECT 3, 'Tim'  FROM DUAL;
    
    CREATE TABLE T2 ( Project, Participants ) AS
    SELECT 0, 'Bob, Bill' FROM DUAL UNION ALL
    SELECT 1, 'Bob, Jill' FROM DUAL UNION ALL
    SELECT 2, 'Bob' FROM DUAL;
    

    输出:

    姓名 |碳纳米管 :--- | --: 比尔 | 1 吉尔 | 1 鲍勃 | 3 蒂姆 | 0

    db小提琴here

    【讨论】:

      猜你喜欢
      • 2013-02-24
      • 1970-01-01
      • 2017-10-09
      • 2010-11-12
      • 2014-11-14
      • 2015-10-08
      • 2013-12-25
      相关资源
      最近更新 更多