在上一篇文章中,我在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)
答案 0 :(得分:10)
使用聚合函数 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:
所有非NULL值的串联
根据the manual,CompanyIds
和Companies
中的元素顺序是任意的:
连接元素的顺序是任意的。
另请注意,“任意”与“随机”不同。与其他聚合函数一样,group_concat
按接收顺序处理行集。没有任何ORDER BY
,该顺序由执行的任何查询计划决定。关系数据库表中没有自然顺序(您不能完全依赖于的插入顺序)。但是同一group_concat()
列表中SELECT
的两个实例都按相同顺序处理行,以便CompanyIds
中的第一个ID对应Companies
中的第一个名称1}}。
您可以在子查询中使用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中的类似聚合函数的行为可能略有不同。相关:
答案 1 :(得分:2)
this post的答案将帮助您转向
Name | company
---------+----------
Doe John | company A
Doe John | company B
进入
Name | company-1 | company-2
---------+-----------+----------
Doe John | company A | company B
答案 2 :(得分:1)
我认为内部选择可能会有所帮助,例如:
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;