2015-06-12 59 views
3

我有一個很大的(ish)數據庫。簡單地把客戶記錄。現在我有兩張桌子;一個是CustomerInfoPhoneNumbers。一些樣本數據是,在SQL Server中爲每條記錄創建行到列

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 
+1

這是一個數據透視查詢。 **重要問題:**您是否可以爲每位客戶提供「無限制」的電話號碼?還是有限制? –

+0

@SQLPolice,我目前沒有超過2個,但是。即使我們有,我也只想要前兩個。謝謝,我會研究這個。 :) – PaulFrancis

回答

5

您可以使用ROW_NUMBER()爲每個電話號碼在其客戶ID內給出一個等級,然後將其用於PIVOT的數據:

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; 

如果您的電話號碼數量未知,並且希望在適用的情況下包含所有電話號碼,我會傾向於使用單個列並顯示逗號分隔列表,您可以使用SQL Server's XML extensions進行此操作。這比使用動態SQL更容易,也爲任何處理的結果更容易,因爲你已經被返回的列的已知數量:

SELECT c.CustID, 
     c.CustName, 
     c.CustomerLocation, 
     PhoneNumbers = STUFF(( SELECT ',' + p.PhoneNumber 
           FROM PhoneNumbers AS p 
           WHERE p.CustID = c.CustID 
           FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 1, '') 
FROM CustomerInfo AS c; 
+0

那麼,如果客戶有5個或更多的號碼,你會怎麼做...... –

+0

@SQLPolice我會增加列數,這是通過改變註釋旁邊的'PIVOT'函數中的數字參數來完成的表示*「根據需要增加/減少列」* – GarethD

+0

是的,但是如果您想要完全靈活? ...寫356欄? ....支持「無限」電話號碼列的唯一解決方案是使用動態SQL編寫過程。 –

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<[email protected]) 
begin 
set @dynamicsql = @dynamicsql +'[PhoneNumber'+convert(nvarchar(10),@counter)+'],' 
set @[email protected]+1 
end 

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

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

print @dynamicsql 
exec (@dynamicsql) 

供您參考

enter image description here

+0

Pravin,毫無疑問,這是有效的,但正如我所提到的,我將此作爲另一個具有其他JOINS的查詢的一部分,所以在那種情況下,我將如何使用動態SQL以及現有的Query? – PaulFrancis

+0

把這個字符串查詢 –

+0

我沒有把這個當作我的答案,但我真的很喜歡你這樣做的方式,我會玩這個。乾杯。:) – PaulFrancis

0

由於加雷,我設法ŧ o找到我的解決方案,我已經接受了他的答案,但是我想我會分享我如何獲得理想的結果。這是我用過的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 
相關問題