SQLITE:如果共享列,则将行合并为单行

发布于 2024-12-11 21:03:37 字数 1033 浏览 0 评论 0原文

从上一篇文章中,我在 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;

现在,由于数据是根据 AttendeeCompany 之间的多对多关系生成的,我可以得到结果,例如:

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)< /代码>

From a previous post, I have the following view in 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;

Now, since the data is generated from a many-to-many relation between Attendee and Company, I can get results such as:

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

What I'd like to do is, in cases where there's more than one company (like above), create a query that outputs:

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

And another that outputs:

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

So I need to know essentially how to merge a specific column for rows that have different
values in that table.

Any ideas?

Just in case, company A company B in the first query is obviously text concatenation, That is, something along the lines of (row1.CompanyName || " " || row2.CompanyName)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

橙味迷妹 2024-12-18 21:03:38

使用聚合函数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 值从结果中排除。 手册:

所有非 NULL 值的串联

CompanyIdsCompanies 中的元素顺序是任意的,根据 手册

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

另请注意,“任意”与“随机”不同。 group_concat 与其他聚合函数一样,按照收到的顺序处理行集。如果没有任何 ORDER BY,则该顺序由执行的任何查询计划决定。关系数据库的表中没有自然顺序(您根本不能依赖插入顺序)。但同一 SELECT 列表中的两个 group_concat() 实例以相同的顺序处理行,以便 CompanyIds< 中的第一个 ID /code> 对应于 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;

有关 ORDER BY代码>:

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

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

排序后,不要对派生表执行任何可能会重新排列的操作(例如将子查询连接到另一个表等)。

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

Use the aggregate function group_concat(X) for that:

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;

(Using table aliases to make it shorter and easier to read.)

NULL values are excluded from the result. The manual:

the concatenation of all non-NULL values

The order of elements in CompanyIds and Companies is arbitrary, according to the manual:

The order of the concatenated elements is arbitrary.

Also note that "arbitrary" is not the same as "random". group_concat, like other aggregate functions, processes the set of rows in the order received. Without any ORDER BY, that order is dictated by whatever query plan is executed. There is no natural order in tables of relational databases (you cannot rely on insert order at all). But both instances of group_concat() in the same SELECT list process rows in the same order so that the 1st ID in CompanyIds corresponds to the 1st name in Companies.

You can impose your order with ORDER BY in a subquery. It's an implementation detail, but it's highly unlikely to change. Like:

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 about the (optional) ordinal numbers in ORDER BY:

If the ORDER BY expression is a constant integer K then the expression is considered an alias for the K-th column of the result set (columns are numbered from left to right starting with 1).

Use the GROUP BY list as leading ORDER BY expressions for best results.

Don't do anything with the derived table after ordering that might rearrange it (like joining the subquery to another table etc.)

Finally, note that similar aggregate functions in other RDBMS can behave slightly differently. Related:

冰雪梦之恋 2024-12-18 21:03:38

这篇文章的答案将为您提供帮助变成

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

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

The answer from this post will help you turn

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

into

Name     | company-1 | company-2
---------+-----------+----------
Doe John | company A | company B
戏剧牡丹亭 2024-12-18 21:03:38

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

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;

I'm thinking a inner select might help, like:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文