为每个连接的记录创建一个新列

时间:2016-03-09 19:45:13

标签: sql sql-server tsql

代理机构可能有很多联系。

Agency

id int
name nvarchar(100)

Contact

id int
email nvarchar(100) 
agency_id int

你如何制作一个存储过程,以便它返回一个包含每个代理商及其联系人的结果集?所以假设你有一个代理商有三个联系人,你最终会得到。

-----------------------------------------------------------------
| agency_name   | contact_1     | contact_2     | contact_3     |
|---------------------------------------------------------------|
| Foo           | Foo1@Foo1.com | Foo2@Foo2.com | Foo3@Foo3.com |
-----------------------------------------------------------------

很明显,人们需要计算代理商可能拥有的加入联系人的最大数量。

2 个答案:

答案 0 :(得分:0)

尝试以下查询:

DECLARE TABLE #temp(name nvarchar(MAX), email nvarchar(MAX), ranking int)
DECLARE @qu NVARCHAR(MAX), @pcol NVARCHAR(MAX)


INSERT INTO #temp
SELECT  
    A.name AS name,
    C.email AS email,
    ROW_NUMBER() OVER (PARTITION BY name ORDER BY email ASC) AS ranking
FROM Agency A LEFT JOIN Contact C ON A.id=C.agency_id


SELECT   
 @pcol= COALESCE(@pcol + ',','') + ContactNumber 
FROM
 (
  SELECT 
        DISTINCT N'Contact'+ CAST (ranking AS NVARCHAR(25)) AS ContactNumber 
  FROM #temp
  ) A

SET @qu=N'SELECT Name,'+ @pcol +  
N'FROM 
    (
      SELECT 
            Name,
            N''Contact''+ CAST (ranking AS NVARCHAR(25)) AS ContactNumber, 
            email 
      FROM #temp
    )S
  PIVOT
  (MAX(email) FOR ContactNumber IN ('+@pcol +N')) AS piv'
EXEC sp_executesql @qu
DROP TABLE #temp

答案 1 :(得分:0)

如果您总是希望显示3列且不会有更多列,则可以将CTEwindow function一起使用,而不是创建动态查询

;WITH C AS(
    SELECT RANK() OVER (PARTITION BY name ORDER BY Email) AS [Rank]
           ,b.id, b.name, Email
    FROM @Contact AS a
    INNER JOIN @Agency AS b ON a.agency_id = b.id
)
SELECT name
    ,MIN(CASE C.[Rank] WHEN 1 THEN Email END) AS [Email1]
    ,MIN(CASE C.[Rank] WHEN 2 THEN Email END) AS [Email2]
    ,MIN(CASE C.[Rank] WHEN 3 THEN Email END) AS [Email3]
FROM C
GROUP BY name