我有一个大(ish)数据库。简单地把客户记录。现在我有两张桌子;一个是CustomerInfo
和PhoneNumbers
。一些样本数据将是,
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
现在您可以看到,Paul
和Francis
只有一个号码,但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
答案 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)
供您参考
答案 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