2017-09-12 76 views
1

我有一個屬性的佔有者列表,需要操縱數據,因此它顯示屬性爲一行,每個額外的居民出現在一個新的列。SQL,使用等級來生成列

這裏是我已經設法到目前爲止做:

Postcode | Number | Occupant | Rank 
AA001AA | 12 | D  | 1 
AA001AA | 12 | E  | 2 
AA001AA | 12 | K  | 3 
AA001AA | 12 | M  | 4 
AA001AA | 12 | T  | 5 
BB001BB | 8 | M  | 1 
BB001BB | 8 | R  | 2 

然後我試着:

with RANKING AS 
( Select 
    Postcode 
    , Number 
    , Occupant 
    , RANK() OVER 
    (Partition by Postcode order by Occupant) as [Rank] 

from Reporting.dbo.Test --order by [Rank] desc 
) 

中排名查詢如下表輸出使用排名的值創建列,如下所示:

Select distinct 
i.Postcode 
, i.Number 
    , case when i.[rank] = 1 then i.Occupant end as [First Tennant] 
    , case when i.[rank] = 2 then i.Occupant end as [Second Tennant] 
    , case when i.[rank] = 3 then i.Occupant end as [Third Tennant] 
    , case when i.[rank] = 4 then i.Occupant end as [Fourth Tennant] 
    , case when i.[rank] = 5 then i.Occupant end as [Fifth Tennant] 

    from Reporting.dbo.Test u 
      inner join RANKING i on i.Postcode = u.Postcode 
0123現在

,2個問題:

1)有沒有什麼辦法,以便爲x的排名,我們有X租戶行自動執行此過程

2)輸出的表是

Postcode | Number | First Tennant | Second Tennant | Third Tennant | Fourth Tennant | Fifth Tennant | 
AA001AA | 12 |  D  |  NULL  |  NULL |  NULL  |  NULL  | 
AA001AA | 12 |  NULL  |   E  |  NULL |  NULL  |  NULL  | 

等等。

如何壓縮此列表,以便每個郵政編碼只有一行,並且所有非空值都出現在該行上。

+0

你需要實際的單詞「第一」,「第二」等?或者只有在那裏有號碼就足夠了?它不會從根本上改變答案,但如果您需要這些答案,則可能需要額外的映射表來將數字映射到其字符串表示形式。 – Xedni

+2

您可以使用動態數據透視將其自動化。列數將等於給定郵編/號碼所需的最大值。對於不包含這些租戶的所有行,將顯示NULL。 – scsimon

+0

任何區分它的方法都行得通,如果有一種方法,例如Tennant(等級值),那很好。 – MichaelL

回答

0

要回答您的第二個問題(如何濃縮列表),最簡單的方法就是group bypostcodenumber。您可以將每列的max()(即如果有一個值,它會被選中;所有的空值都會丟失)。

要回答第一個問題(可以自動執行),您可能需要查看動態數據透視表。在評論中發表的一篇文章是這樣的:SQL Server dynamic PIVOT query?

這個想法基本上是爲了序列化不同的tennants,並將它連接到一個動態的SQL字符串中來執行一個數據透視。有幾種方法可以給這隻貓蒙皮,但這就是我如何接近它。

use tempdb 
go 

if object_id('tempdb.dbo.#data') is not null drop table #data 
create table #data 
(
    PostCode varchar(10), 
    Number int, 
    Occupant char(1), 
    Rnk int, 
    ColName as 'Tennant ' + cast(Rnk as varchar(10)) 

) 

insert into #Data(PostCode, Number, Occupant, Rnk) 
select 'AA001AA', 12, 'D',1 
union all select 'AA001AA', 12, 'E',2 
union all select 'AA001AA', 12, 'K',3 
union all select 'AA001AA', 12, 'M',4 
union all select 'AA001AA', 12, 'T',5 
union all select 'BB001BB', 8, 'M',1 
union all select 'BB001BB', 8, 'R',2 

declare 
    @PivotColumns nvarchar(max), 
    @SelectColumns nvarchar(max), 
    @sql nvarchar(max) 

select 
    @PivotColumns = stuff((select ',' + quotename(ColName) 
         from #data 
         group by ColName 
         order by ColName 
         for xml path('')), 1, 1, ''), 
    @SelectColumns = stuff((select ',' + quotename(ColName) + ' = max(' + quotename(ColName) + ')' 
          from #data 
          group by ColName 
          order by ColName 
          for xml path('')), 1, 1, ''), 
    @sql = ' 
     select 
      PostCode, 
      Number, 
      ' + @SelectColumns + ' 
     from #data d 
     pivot (max(Occupant) for ColName in (' + @PivotColumns + ')) p 
     group by PostCode, Number' 


print @sql 
exec sp_executesql @sql 
0

您可以使用動態數據透視表來獲得您的結果。請看下面的代碼 -

create table #tab (Postcode varchar(10) , Number int , Occupant char(1) , Rank int) 

insert into #tab 
select 'AA001AA' , 12 , 'D'  , 1 
union all select 'AA001AA' , 12 , 'E'  , 2 
union all select 'AA001AA' , 12 , 'K'  , 3 
union all select 'AA001AA' , 12 , 'M'  , 4 
union all select 'AA001AA' , 12 , 'T'  , 5 
union all select 'BB001BB' , 8 , 'M'  , 1 
union all select 'BB001BB' , 8 , 'R'  , 2 
union all select 'CC001CC' , 8 , 'N'  , 1 
union all select 'CC001CC' , 8 , 'O'  , 2 
union all select 'CC001CC' , 8 , 'P'  , 3 
union all select 'CC001CC' , 8 , 'Q'  , 4 
union all select 'CC001CC' , 8 , 'R'  , 5 
union all select 'CC001CC' , 8 , 'S'  , 6 
union all select 'CC001CC' , 8 , 'T'  , 7 
union all select 'CC001CC' , 8 , 'U'  , 8 
union all select 'CC001CC' , 8 , 'V'  , 9 
union all select 'CC001CC' , 8 , 'W'  , 10 

declare @mx int , @min int = 1 , @sql nvarchar(max) = '' , @select1 nvarchar(max) = '',@select2 nvarchar(max) = '' 

select @mx = MAX(rank) from #tab 

while @min<= @mx 
begin 
set @select1 = @select1 + '[' + cast(@min as varchar(10))+ '] ,' 
set @select2 = @select2 + '[' + cast(@min as varchar(10))+ '] as '+ '[Tennant_' + cast(@min as varchar(10))+ '] ,' 
set @min = @min + 1 
end 

set @select1 = SUBSTRING(@select1 , 1 , LEN(@select1)-1) 
set @select2 = SUBSTRING(@select2 , 1 , LEN(@select2)-1) 


set @sql = ' 
SELECT Postcode , Number ,'[email protected]+' 
FROM #tab 
PIVOT 
(
    max(Occupant) 
    FOR [Rank] IN ('[email protected]+') 
)AS pvt ' 

exec sp_executesql @sql