SQL - 组合一个值的结果(行)

时间:2012-09-06 00:42:15

标签: sql

我认为这是一个新手问题,但我没想出任何东西就是我的搜索。

两张桌子:

表1名称:客户端

Inactive    ClientID    Name
0           1001        Fred
0           1002        Cindy
0           1003        John
0           1004        Sherry

表2名称:JOURNAL

ClientID    RecordType  Date       Comments
1001        Note       01-01-2012   TXT1
1001        Note       01-01-2012   TXT2
1003        Note       01-01-2012   TXT3
1001        Note       01-02-2012   TXT4
1002        Note       01-06-2012   TXT5
1003        Note       01-22-2012   TXT6
1003        Note       01-23-2012   TXT7

如果无法知道JOURNAL中的特定ClientID将有多少行。可能是没有或很多。

如果我使用以下内容,除了1004之外的所有内容,这是我的第一个问题。

SELECT FROM CLIENT.InActive, CLIENT.ClientID, CLIENT.Name, JOURNAL.Comments
LEFT OUTER JOIN JOURNAL ON CLIENT.ClientID = JOURNAL.ClientID
WHERE CLIENT.Inactive = 0 and JOURNAL.Date > '2011-01-01'

我要做的是将JOURNAL.Comments的结果合并到一个记录中。

ClientID    Name    Comments
1001        Fred    TXT1, TXT2, TXT4
1002        Cindy   TXT5
1003        John    TXT3, TXT6, TXT7
1004        Sherry

更新:我从Faircom ODBC源中提取数据,因此我受限制且无法将CREATE用于TMP表。使用Excel或MSQUERY,因为我无法通过SMS连接到FairCom驱动程序。

任何建议将不胜感激。是的......我知道别名'。想要保持简单,因为我很难抓住这个。

3 个答案:

答案 0 :(得分:4)

首先,您没有收到1004记录,因为您放置了date过滤器,将其移至left join

select c.inactive,
  c.clientid,
  c.name,
  j.comments
from client c
left join journal j
  on c.clientid = j.clientid
  and j.dt > '2011-01-01'
where c.inactive = 0

其次,你没有指定RDBMS,所以这里有一些选项:

在SQL Server中,您可以使用STUFF()

select c.inactive,
  c.clientid,
  c.name,
  STUFF((SELECT distinct ', ' + comments 
              from journal j
              where j.clientid = c.clientid
                 and j.dt > '2011-01-01'
            FOR XML PATH(''), TYPE

            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')
from client c
where c.inactive = 0

请参阅SQL Fiddle with Demo

在MySQL中使用GROUP_CONCAT()

select c.inactive,
  c.clientid,
  c.name,
  GROUP_CONCAT(COALESCE(j.comments, 'NULL'))
from client c
left join journal j
  on c.clientid = j.clientid
  and j.dt > '2011-01-01'
where c.inactive = 0
GROUP BY c.inactive,
  c.clientid,
  c.name

请参阅SQL Fiddle with Demo

在Oracle中,您可以使用listagg()函数:

select c.inactive,
  c.clientid,
  c.name,
  LISTAGG(j.comments, ',') WITHIN GROUP (ORDER BY c.clientid) AS comments
from client c
left join journal j
  on c.clientid = j.clientid
  and j.dt > to_date('2011-01-01', 'yyyy-mm-dd')
where c.inactive = 0
GROUP BY c.inactive,
  c.clientid,
  c.name

请参阅SQL Fiddle with Demo

答案 1 :(得分:3)

这是使用CROSS APPLY

的另一个版本
SELECT a.inactive , 
       a.clientid,
       a.name,
       SUBSTRING(d.CommentsList,1, LEN(d.CommentsList) - 1) CommentsList
FROM   client a
       CROSS APPLY
       (
          SELECT comments + ', ' 
          FROM journal AS B 
          WHERE A.clientid = B.clientid 
          FOR XML PATH('')
        ) D (CommentsList) 

SQLFiddle Demo

特别感谢SQLFiddle DDL

bluefeet

答案 2 :(得分:2)

对于SQL Server 2008,这是解决方案,添加where子句

SELECT  ClientID   ,Name ,Comments= STUFF((SELECT ','+ yt.Comments
                                                    FROM JOURNAL yt
                                                    WHERE yt.ClientID = sc.ClientID            
                                                    FOR XML PATH(''), TYPE).value('.','VARCHAR(max)'), 1, 1, '')
         FROM CLIENT AS sc