在SQL Server中为每个记录创建行

时间:2015-06-12 11:26:57

标签: sql-server sql-server-2012

我有一个大(ish)数据库。简单地把客户记录。现在我有两张桌子;一个是CustomerInfoPhoneNumbers。一些样本数据将是,

CustomerInfo
`````````````
CustID  |   CustName    |   CustomerLocation
--------+---------------+--------------------
1       |   Paul        |   Bristol
2       |   Eugin       |   Bournemouth
3       |   Francis     |   London

PhoneNumbers
````````````
PhoneID |   CustID  |   PhoneNumber
--------+-----------+----------------
1       |   1       |   0117123456
2       |   2       |   0120212345
3       |   2       |   0784256864
4       |   3       |   0204587895

现在您可以看到,PaulFrancis只有一个号码,但Eugin有两个号码。在正常的世界中,如果我加入两个表格,

SELECT
    c.CustName,
    p.PhoneNumber
FROM
    CustomerInfo c
    JOIN 
    PhoneNumbers p
    ON c.CustID = p.CustID

我会的,

CustName    |   PhoneNumber
------------+--------------------
Paul        |   0117123456
Eugin       |   0120212345
Eugin       |   0784256864
Francis     |   0204587895

这是对的,但是我正在运行另一个需要结果的查询,

CustName    |   PhoneNumber1    |   PhoneNumber2
------------+-------------------+---------------
Paul        |   0117123456      |   NULL
Eugin       |   0120212345      |   0784256864
Francis     |   0204587895      |   NULL

我可以从函数中编写一个表变量。但由于这将成为查询的一部分,我希望是否有任何其他解决方案。

编辑 - 我想强调一下as this is going to be part of a Query, I was hoping if there were any other solution部分,实际查询将会是,

SELECT 
    per.[PersonId],
    per.[ClientReference],
    sal.SalutationName,
    per.[FirstName],
    per.[LastName],
    per.[DateOfBirth],
    per.[Password]
FROM 
    [Customers].[people].[Person] per
    JOIN 
    [Customers].[people].[Salutation] sal
    ON sal.SalutationId = per.SalutationId

我想要的是,

SELECT 
    per.[PersonId],
    per.[ClientReference],
    sal.SalutationName,
    per.[FirstName],
    per.[LastName],
    per.[DateOfBirth],
    per.[Password],
    pn.[PhoneNumber1], --Made up column, there is only one column in the pn table
    pn.[PhoneNumber2]  --Made up column, there is only one column in the pn table
FROM 
    [Customers].[people].[Person] per
    JOIN 
    [Customers].[people].[Salutation] sal
    ON sal.SalutationId = per.SalutationId
    JOIN 
    [Customers].[comms].[PhoneNumber] pn
    ON per.PersonId = pn.PersonId

3 个答案:

答案 0 :(得分:5)

您可以使用ROW_NUMBER()为每个电话号码在其客户ID中提供排名,然后将其用于PIVOT数据:

Split(new char[]{'\t'});

如果你有一个未知数量的电话号码,并希望将它们全部包含在适用的地方,我倾向于使用单个列并显示逗号分隔列表,你可以使用SQL Server's XML extensions来完成。这比使用动态SQL更容易,并且对于处理结果的任何事情也更容易,因为您返回了已知数量的列:

SELECT  CustID,
        PhoneNumber1 = pvt.[1],
        PhoneNumber2 = pvt.[2],
        PhoneNumber3 = pvt.[3],
        PhoneNumber4 = pvt.[4]
FROM    (   SELECT  CustID, 
                    PhoneNumber,
                    RowNum = ROW_NUMBER() OVER(PARTITION BY CustID ORDER BY Phonenumber)
            FROM    PhoneNumbers 
        ) AS pn
        PIVOT 
        (   MAX(Phonenumber)
            FOR RowNum IN ([1], [2], [3], [4]) -- INCREASE/DECREASE COLUMNS AS REQUIRED
        ) AS pvt;

答案 1 :(得分:2)

这就是你想要的,使用动态SQL进行透视

declare @maxcount as int = (select top 1 count(phonenumber) from PhoneNumbers group by custid order by count(phonenumber) desc)
declare @dynamicsql as nvarchar(max) = 'select * from
(
SELECT
    c.CustName,
    p.PhoneNumber,
    ''PhoneNumber''+convert(nvarchar(10),(row_number() over (partition by custname order by c.CustName))) as rn
FROM
    CustomerInfo c
    inner join 
    PhoneNumbers p
    ON c.CustID = p.CustID
) as sourcetable
pivot
(
    MAX(Phonenumber)
    FOR rn IN ('

declare @counter as int = 1
while (@counter<=@maxcount)
begin
set @dynamicsql = @dynamicsql +'[PhoneNumber'+convert(nvarchar(10),@counter)+'],'
set @counter=@counter+1
end

set @dynamicsql = substring(@dynamicsql,0,len(@dynamicsql))

set @dynamicsql = @dynamicsql + ')
)
as pivottable'

print @dynamicsql
exec (@dynamicsql)

供您参考

enter image description here

答案 2 :(得分:0)

感谢Gareth,我设法找到了我的解决方案,我接受了他的回答,但我想我会分享我是如何设法得到理想的结果的。这是我用过的SQL。

SELECT 
    per.[PersonId],
    per.[ClientReference],
    sal.SalutationName,
    per.[FirstName],
    per.[LastName],
    per.[DateOfBirth],
    per.[Password],
    tmpQ.PhoneNumber1,
    tmpQ.PhoneNumber2
FROM 
    [Customers].[people].[Person] per
    JOIN 
    [Customers].[people].[Salutation] sal
    ON sal.SalutationId = per.SalutationId
    JOIN 
    (SELECT  
         [PersonId],
         PhoneNumber1 = pvt.[1],
         PhoneNumber2 = pvt.[2]
     FROM (SELECT  
              [PersonId], 
              Number,
              RowNum = ROW_NUMBER() OVER(PARTITION BY PersonID ORDER BY Number)
           FROM [Customers].[comms].[PhoneNumber]) AS pn
           PIVOT (MAX(Number) FOR RowNum IN ([1], [2])) AS pvt
     ) tmpQ 
    ON tmpQ.PersonId = per.PersonId