【问题标题】:SQLITE: merging rows into single row if they share a columnSQLITE:如果它们共享一列,则将行合并为单行
【发布时间】:2011-12-13 14:55:33
【问题描述】:

从上一篇文章中,我在 sqlite3 中有以下视图:

CREATE View AttendeeTableView AS

SELECT  (LastName || " " || FirstName) as AttendeeName,  
        CompanyName, 
        PhotoURI,
        CompanyAttendeeRelation.CompanyId,
        CompanyAttendeeRelation.AttendeeId 

FROM    Attendee 
JOIN    CompanyAttendeeRelation on CompanyAttendeeRelation.AttendeeId = Attendee.AttendeeId 

ORDER BY LastName;

现在,由于数据是从Attendee 和Company 之间的多对多关系生成的,我可以得到如下结果:

Doe John | company A | johnPic.png | 1 | 15
Doe John | company B | johnPic.png | 2 | 15

我想做的是,如果有不止一家公司(如上),创建一个输出的查询:

Doe John | company A company B | johnPic.png | 1 2 | 15

还有一个输出:

Doe John | company A | company B | johnPic.png | 1 | 2 | 15

所以我基本上需要知道如何合并具有不同行的特定列 该表中的值。

有什么想法吗?

以防万一,第一个查询中的company A company B显然是文本连接,即类似于(row1.CompanyName || " " || row2.CompanyName)的内容

【问题讨论】:

    标签: sql database sqlite aggregate-functions


    【解决方案1】:

    为此使用聚合函数group_concat(X):

    SELECT (a.LastName || " " || a.FirstName) AS AttendeeName
         , a.PhotoURI
         , group_concat(c.CompanyName) AS Companies
         , group_concat(c.CompanyId)   AS CompanyIds
    FROM   Attendee AS a
    JOIN   CompanyAttendeeRelation AS ca ON ca.AttendeeId = a.AttendeeId
    JOIN   Company                 AS c  ON c.CompanyId = ca.CompanyId
    GROUP  BY a.LastName, a.Firstname, a.PhotoURI;
    

    (使用表格别名使其更短且更易于阅读。)

    NULL 值从结果中排除。 The manual:

    所有非空值的串联

    CompanyIds和Companies中的元素顺序是任意的,根据the manual:

    连接元素的顺序是任意的。

    另请注意,“任意”与“随机”不同。 group_concat 与其他聚合函数一样,按接收顺序处理行集。如果没有任何ORDER BY,则该顺序由执行的任何查询计划决定。关系数据库的表中没有自然顺序(您不能完全依赖插入顺序)。但是group_concat() 的两个实例在同一SELECT 中以相同 的顺序列出进程行,因此CompanyIds 中的第一个ID 对应于Companies 中的第一个名称。

    您可以在子查询中使用ORDER BY 强加您的订单。这是一个实现细节,但极不可能改变。喜欢:

    SELECT (LastName || " " || FirstName) AS AttendeeName
         , PhotoURI
         , group_concat(CompanyName) AS Companies
         , group_concat(CompanyId)   AS CompanyIds
    FROM  (
       SELECT a.LastName, a.FirstName, a.PhotoURI, c.CompanyName, c.CompanyId
       FROM   Attendee AS a
       JOIN   CompanyAttendeeRelation AS ca ON ca.AttendeeId = a.AttendeeId
       JOIN   Company                 AS c  ON c.CompanyId = ca.CompanyId
       ORDER  BY 1,2,3,4,5  -- or whatever you need
       ) AS sub
    GROUP  BY LastName, Firstname, PhotoURI;
    

    The manual 关于ORDER BY 中的(可选)序数:

    如果 ORDER BY 表达式是一个常数整数 K,则该表达式被视为结果集第 K 列的别名(列从左到右从 1 开始编号)。

    使用GROUP BY 列表作为前导ORDER BY 表达式以获得最佳结果。

    在排序后不要对派生表做任何可能重新排列它的事情(比如将子查询连接到另一个表等)

    最后,请注意,其他 RDBMS 中类似的聚合函数的行为可能略有不同。相关:

    【讨论】:

    • 手册说The order of the concatenated elements is arbitrary。这是否意味着串联的CompanyIds 不一定按照Companies 的顺序匹配?
    • @Jason:我添加了更多来解决这个问题(除其他外)。
    【解决方案2】:

    this post的回答会帮你转

    Name     | company
    ---------+----------
    Doe John | company A
    Doe John | company B
    

    进入

    Name     | company-1 | company-2
    ---------+-----------+----------
    Doe John | company A | company B
    

    【讨论】:

      【解决方案3】:

      我认为内部选择可能会有所帮助,例如:

      CREATE View AttendeeTableView AS
      
      SELECT  (LastName || " " || FirstName) as AttendeeName,  
      
      (
        select CompanyName
      FROM    Attendee A_innner 
      JOIN    CompanyAttendeeRelation CAR  /* is this where company name is? */  
      ON      on CAR.AttendeeId = A.AttendeeId /* if not remove the joins and CAR */
      WHERE   A_inner.last_name = A_outer.last_name and
              A_inner.first_name = A_outer.first_name
      ),
      PhotoURI,
      CAR.CompanyId,
      CAR.AttendeeId 
      
      
      FROM    Attendee A_outer 
      JOIN    CompanyAttendeeRelation CAR_outer  
      ON      on CAR_outer.AttendeeId = A_outer.AttendeeId 
      
      GROUP by LastName,FirstName
      ORDER BY LastName, FirstName;
      

      【讨论】:

        猜你喜欢
        • 2016-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-28
        • 2020-08-18
        • 2019-09-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多