2014-05-02 48 views
3

UPDATESQL支點,沒有聚集

我已經修改了SQL小提琴,使部門名稱更能反映什麼,我試圖去。如果你看小提琴有3個選擇語句。

  1. 列出了正確的順序部門從我嘗試了數據
  2. 結果在樞軸
  3. 假SELECT以顯示什麼,我試圖去

在結果我的樞軸嘗試第二行顯示的是departmentLevel1的空值,而departmentLevel3不應該在這一行中。我嘗試過row_number和分區的各種組合,但我似乎無法弄清楚這一點。 完全沮喪!

這裏是我的最新小提琴http://sqlfiddle.com/#!3/175af/40

之前你投票CLOSE 請仔細閱讀這個問題,然後讀取選址爲重複的問題。這個問題更加簡單。我的問題不僅要求關於樞軸轉動,而且要將樞軸結果分組,並且要做更多的轉動起止時間。我認爲只是看標題。如果你不想閱讀完整的問題,但不要認爲它與其他類似題目的問題一樣。

我意識到我必須有一個聚合,所以我嘗試使用max,但我真的只是試圖以更多的表格方式顯示此信息,所以我可以將其加入到另一個數據集。

這裏是開始時的資料:

select departmentID, departmentParentID, departmentName, departmentGroupSortBy, departmentLevel, sortBy 
from vDepartmentList 
where regionID = 3 
order by departmentGroupSortBy, departmentLevel, sortBy 

departmentID departmentParentID departmentName departmentGroupSortBy departmentLevel sortBy 
--------------------------------------------------------------------------------------------------- 
111         neth test dept 1      1    1 
115    111     test sub1  1      2    1 
112         test2   2      1    2 
113    112     new sub2  2      2    1 
114    112     new sub 3a  2      2     2 
116    114     should L3  2      3     1 

如果我運行此查詢:

select departmentParentID, [1] as departmentLevel1, [2] as departmentLevel2, [3] as departmentLevel3 
from (
    select departmentParentID, departmentLevel, departmentName 
    from vDepartmentList 
    where regionID = 3 
    ) p 
pivot (
    max(departmentName) 
    for departmentLevel in ([1],[2],[3]) 
    ) as pvt 
order by departmentParentID 

我得到這樣的結果:

departmentParentID departmentLevel1 departmentLevel2 departmentLevel3 
---------------------------------------------------------------------------- 
        test2  
111          test sub1 
112          new sub2  
114               should L3 

但我想獲得的:

departmentParentID departmentLevel1 departmentLevel2 departmentLevel3 
---------------------------------------------------------------------------- 
111     neth test dept  test sub1 
112     test2    new sub2  
112     test2    new sub 3a   should L3 

有沒有人對我出錯的地方有什麼建議?

+2

在您的子查詢中使用'row_number()'爲parentid級別的每個項目創建一個唯一值。這將允許多行返回 – Taryn

+0

可能重複的[SQL Server:透視功能,需要透視表](http://stackoverflow.com/questions/20103646/sql-server-pivot-functionality-need-to- pivot-a-table) – Lamak

+0

沒有不重複。部門級別的複雜性使得它與簡單地調整開始和停止時間大不相同。也許這是我的問題的一部分,試圖做一次做許多事情 – Lance

回答

3

既然你需要返回3個級別的層級數據結構,它可能會更容易使用JOIN而不是使用P IVOT。您將從返回父行開始:

select p.departmentName 
from dbo.department p 
where p.departmentParentID is null; 

這將爲您帶來所有頂級行。然後,您開始爲每個需要的附加關卡添加連接,在您的情況下,您需要總共三個關卡,以便您添加兩個連接。最終查詢將如下:

select p.departmentName department1, 
    c.departmentName department2, 
    gc.departmentName department3 
from dbo.department p   -- parent level 
left join dbo.department c -- child level 
    on p.departmentID = c.departmentParentID 
left join dbo.department gc -- grandchild level 
    on c.departmentID = gc.departmentParentID 
where p.departmentParentID is null; 

請參閱SQL Fiddle with Demo

看來,使用JOIN而不是使用PIVOT可以更容易地得到結果。這使用源數據而不是您創建的遞歸視圖。這給出了一個結果:

| DEPARTMENT1 | DEPARTMENT2 | DEPARTMENT3 | 
|-------------|-------------|--------------| 
|  depart1 |  d1 sub1 |  (null) | 
|  depart2 |  d2 sub |  (null) | 
|  depart2 |  d2 sub2 | d2s2 subSub1 | 

如果你想使用遞歸查詢得到的結果,那麼你可以稍微改變當前視圖返回的名稱,而不是等級數值的3列:

;with cte as 
(
    select departmentID, 
     departmentParentID, 
     departmentName as Department1, 
     cast(null as varchar(100)) Department2, 
     cast(null as varchar(100)) Department3, 
     1 as Level 
    from dbo.department 
    where departmentParentID is null 
    union all 
    select d.departmentID, 
     d.departmentParentID, 
     Department1, 
     case when Level + 1 = 2 then d.departmentName else Department2 end, 
     case when Level + 1 = 3 then d.departmentName else Department3 end, 
     Level + 1 
    from dbo.department d 
    inner join cte h 
     on d.departmentParentID = h.departmentID 
) 
select * 
from cte; 

請參閱SQL Fiddle with Demo。然後,您可以使用WHERE子句進行一些篩選,以返回具有您需要的所有部門值的行。

+0

真棒@bluefeet謝謝。我想我專注於一個複雜的問題,真的需要退後一步,從簡單的方法來看待它。簡單而簡單! – Lance

+0

@蘭斯是啊,當你最初發布它似乎是一個簡單的支點,這就是爲什麼我建議行號,但一旦你提供了其他細節,很明顯,使用連接查詢會更容易 – Taryn

0

旋轉就像分組一樣。您需要原始來源中的一列進行分組。在這種情況下,你沒有它,並且支點不知道'test sub1'以任何方式連接到'neth test dept'。我們在這裏需要的是建立層次結構的根。

;with x as (
    select *, departmentID as root 
    from #t 
    where departmentParentID is null 
    union all 
    select #t.*, x.root 
    from #t 
    inner join x on #t.departmentParentID = x.departmentID 
) 
select * 
from x 

所以現在我們有一個根,也花葯的問題,以及:我們可以用一個小的遞歸CTE(與vDepartmentList替換#T)做到這一點,我們只有兩個根,但你想擁有三排在結果中。樞軸操作者將基本上在根列上進行分組,並且將視爲屬於'test2'的'新的子2','新的子3a'和'應該L3',並且產生具有這些值的相應最大值的單個行。

應該有一種區分方法,但我無法在數據中看到它。所以,看起來,你運氣不好。

+0

嗨@dean我做了一個sql小提琴http://sqlfiddle.com/#!3/47d36/2/6因爲這是不容易的,我解釋。遞歸CTE是我認爲我正在嘗試旋轉的觀點,但也許我做錯了。如果你有機會看小提琴,看看我搞砸了什麼,我很感激 – Lance

1


我基於你的視圖sql創建了下面的sql。你幾乎可以在那裏得到結果。

我使用@temp表刪除order by子句。可能你可以在實現中刪除@temp表。

請嘗試以下SQL:

declare @temp table 
(
    id int identity, 
    departmentLevel1 int, 
    departmentLevel2 int, 
    departmentLevel3 int, 
    xRow int 
) 

insert into @temp 
select 
    d.lvl1, d.lvl2, d.lvl3 
    ,Rrow 
from 
(
select 
    a.lvl1, a.lvl2, a.lvl3 
    ,row_number() over(partition by a.lvl1,a.lvl2 order by a.lvl1,a.lvl2) as Rrow 
    ,departmentGroupSortby, departmentlevel, sortby 
from 
    vDepartmentList a 
) d 
where (d.lvl2 is not null) 
order by departmentGroupSortby, departmentlevel, sortby 
; 

select 
    c.departmentLevel1 as departmentParentID 
    ,Case 
     when c.departmentLevel1 = d.departmentid then d.DepartmentName 
     else 
      null 
    end as DepartmentLevel1 
    ,Case 
     when c.departmentLevel2 = e.departmentid then e.DepartmentName 
     else 
      null 
    end as DepartmentLevel2 
    ,Case 
     when c.departmentLevel3 = f.departmentid then f.DepartmentName 
     else 
      null 
    end as DepartmentLevel3 
    --,d.departmentId ,e.departmentid ,f.departmentid 
from 
(
select 
    a.id, a.departmentLevel1,a.departmentLevel2,a.departmentLevel3 
    ,a.xRow 
from @temp a 
inner join 
(
select 
    cast(departmentLevel1 as nvarchar(5)) + cast(departmentLevel2 as nvarchar(5)) as xrow, count(cast(departmentLevel1 as nvarchar(5)) + cast(departmentLevel2 as nvarchar(5))) as xcount 
from @temp 
group by cast(departmentLevel1 as nvarchar(5)) + cast(departmentLevel2 as nvarchar(5)) 
) b on cast(a.departmentLevel1 as nvarchar(5)) + cast(a.departmentLevel2 as nvarchar(5)) = b.xrow and a.xRow = b.xcount 
) c 
left join department d on c.departmentLevel1 = d.departmentId 
left join department e on c.departmentLevel2 = e.departmentid 
left join department f on c.departmentLevel3 = f.departmentid 



結果

departmentParentID DepartmentLevel1 DepartmentLevel2 DepartmentLevel3 
------------------ ---------------- ---------------- ---------------- 
111    depart1   d1 sub1   NULL 
112    depart2   d2 sub   NULL 
112    depart2   d2 sub2   d2s2 subSub1 

希望這是幫助

+0

Thx @cyan。因爲你是正確的,所以我給你一個滿意的答覆。我打算標記Bluefeet的答案是爲了簡單。 – Lance

+0

很酷,祝你好運先生 – cyan