2017-09-07 36 views
5

Mam tabeli wygląda następującoobrotowe wierszy 14 kolumnach 7 krotek

assignmentID personID projectCode projectCodePercent 
-------------- ------------ ----------- ----------- 
642    13527  511   75.00 
642    13527  621   25.00 
650    12000  555   50.00 
650    12000  520   25.00 
650    12000  621   25.00 
240    56000  721   100.00 

chcę wiedzieć, dystrybucję (porjectCode, projectCodePercent) W krotce dla każdego zadania. Przypisanie może mieć do 7 krotek. jeśli nie mają 7, to pole może być puste. Tak więc pożądana moc powinna wyglądać poniżej:

assignmentID projectCode1 projectCodePercent1 projectCode2 projectCodePercent2 projectCode3 projectCodePercent3 projectCode4 projectCodePercent4 projectCode5 projectCodePercent5 projectCode6 projectCodePercent6 projectCode7 projectCodePercent7 
------------ ------------ ------------------- ------------ ------------------- ------------- ------------------- ------------- ------------------- ------------- ------------------- ------------- ------------------- ------------ ---------------- 
642   511   75.00     621   25.00 
650   555   50.00     520   25.00     621    25.00 
240   721   100.00 

EDYCJA: kolejność zapisu nie ma znaczenia. to znaczy. które rejestrują dostaje przypisać projectCode1 lub projectCode2 .... i tak dalej, nie ma znaczenia, tak długo, jak prawo projectCode mecze Prawidłowe projectCodePercent

+0

Co określa rozkazy rekordu? Dlaczego 520 projectcode2 zamiast 555 lub 621? Losowy? nie ma znaczenia? – xQbert

+0

@xQbert Dziękujemy za wyjaśnienie. kolejność rekordów nie ma znaczenia. –

Odpowiedz

3

Ponieważ nie trzeba iść dynamiczne. Jednym ze sposobów jest UNPivot danych za pomocą aplikacji CROSS APPLY.

Przykład

Select * 
From (
     Select assignmentID  
       ,B.* 
      From (
        Select *,Grp = Row_Number() over (Partition By assignmentID order by projectCode) 
        From YourTable 
       ) A 
      Cross Apply (values ('projectCode'  +left(A.Grp,1),cast(projectCode as varchar(max))) 
           ,('projectCodePercent'+left(A.Grp,1),cast(projectCodePercent as varchar(max))) 
           ,('projectCode'  +left(A.Grp,1),cast(projectCode as varchar(max))) 
         ) B(Item,Value) 
    ) A 
Pivot (max([Value]) For [Item] in (projectCode1,projectCodePercent1,projectCode2,projectCodePercent2,projectCode3,projectCodePercent3,projectCode4,projectCodePercent4,projectCode5,projectCodePercent5,projectCode6,projectCodePercent6,projectCode7,projectCodePercent7)) p 

Zwraca

enter image description here

+1

Tyle czystsze (z punktu widzenia wykonania) niż to, co zrobiłem. Naprawdę muszę grać z krzyżem, aplikuj więcej. Chociaż nie zazdroszczę nowej osobie, która musi utrzymywać powyższe na początku: P – xQbert

+1

@xQbert Ponieważ był to stały numer, moją pierwszą myślą było twoje podejście. Po prostu postaw na alternatywę. –

+2

Dobra w tym: P powinna zawsze korzystać z nowych funkcji, gdy można. Oferują zwykle znaczące korzyści. – xQbert

4

Demo: http://rextester.com/IYDJ29385

  1. CTE daje mi przykładowe dane do zabawy
  2. CTE2 po prostu przypisuje numer wiersza do każdego przydziału i Indywidualnego (można użyć widoku liniowego)
  3. Następnie używamy instrukcji case, aby przestawić dane na podstawie wygenerowanych numerów wierszy. Upadek tego podejścia polega na tym, że wszystkie 14 kolumn są zawsze zwracane. Używając dynamicznego SQL, możesz wyświetlać te kolumny tylko wtedy, gdy są potrzebne.

Zakłada się, że atrybut assignId oraz personId i projectcode są unikalne. Gdyby istniało wiele kodów projektu dla tego samego zadania i osoby, musielibyśmy zrobić coś innego zamiast max.

WITH CTE (assignmentID, personID, projectCode, projectCodePercent) as (
SELECT 642,    13527,  511,   75.00 UNION ALL 
SELECT 642,    13527,  621,   25.00 UNION ALL 
SELECT 650,    12000,  555,   50.00 UNION ALL 
SELECT 650,    12000,  520,   25.00 UNION ALL 
SELECT 650,    12000,  621,   25.00 UNION ALL 
SELECT 240,    56000,  721,   100.00), 
cte2 as (SELECT A.*, row_number() over (partition by AssignmentID, PersonID order by projectCode) RN 
     FROM cte A) 
SELECT AssignmentID 
    , PersonID 
    , max(CASE WHEN RN = 1 then projectCode end) as projectCode1 
    , max(CASE WHEN RN = 1 then ProjectcodePercent end) as ProjectcodePercent1 
    , max(CASE WHEN RN = 2 then projectCode end) as projectCode2 
    , max(CASE WHEN RN = 2 then ProjectcodePercent end) as ProjectcodePercent2 
    , max(CASE WHEN RN = 3 then projectCode end) as projectCode3 
    , max(CASE WHEN RN = 3 then ProjectcodePercent end) as ProjectcodePercent3 
    , max(CASE WHEN RN = 4 then projectCode end) as projectCode4 
    , max(CASE WHEN RN = 4 then ProjectcodePercent end) as ProjectcodePercent4 
    , max(CASE WHEN RN = 5 then projectCode end) as projectCode5 
    , max(CASE WHEN RN = 5 then ProjectcodePercent end) as ProjectcodePercent5 
    , max(CASE WHEN RN = 6 then projectCode end) as projectCode6 
    , max(CASE WHEN RN = 6 then ProjectcodePercent end) as ProjectcodePercent6 
    , max(CASE WHEN RN = 7 then projectCode end) as projectCode7 
    , max(CASE WHEN RN = 7 then ProjectcodePercent end) as ProjectcodePercent7 
FROM CTE2 
Group by AssignmentID, personId 

dając nam:

+----+--------------+----------+--------------+---------------------+--------------+---------------------+--------------+---------------------+--------------+---------------------+--------------+---------------------+--------------+---------------------+--------------+---------------------+ 
| | AssignmentID | PersonID | projectCode1 | ProjectcodePercent1 | projectCode2 | ProjectcodePercent2 | projectCode3 | ProjectcodePercent3 | projectCode4 | ProjectcodePercent4 | projectCode5 | ProjectcodePercent5 | projectCode6 | ProjectcodePercent6 | projectCode7 | ProjectcodePercent7 | 
+----+--------------+----------+--------------+---------------------+--------------+---------------------+--------------+---------------------+--------------+---------------------+--------------+---------------------+--------------+---------------------+--------------+---------------------+ 
| 1 |   650 | 12000 |   520 |    25,00 | 555   | 50,00    | 621   | 25,00    | NULL   | NULL    | NULL   | NULL    | NULL   | NULL    | NULL   | NULL    | 
| 2 |   642 | 13527 |   511 |    75,00 | 621   | 25,00    | NULL   | NULL    | NULL   | NULL    | NULL   | NULL    | NULL   | NULL    | NULL   | NULL    | 
| 3 |   240 | 56000 |   721 |    100,00 | NULL   | NULL    | NULL   | NULL    | NULL   | NULL    | NULL   | NULL    | NULL   | NULL    | NULL   | NULL    | 
+----+--------------+----------+--------------+---------------------+--------------+---------------------+--------------+---------------------+--------------+---------------------+--------------+---------------------+--------------+---------------------+--------------+---------------------+ 
+0

Lepsza opcja z punktu widzenia planu wykonania – JamieD77

+0

+ 1 Dzięki. Podoba mi się to, ponieważ jest to łatwe do zrozumienia. Planuję używać tego jako mojego podzapytania. moje obecne zapytanie jest już bardzo duże i złożone, więc mogę użyć odpowiedzi Johna poniżej. –

+0

Złożony SQL to jeden z powodów, dla których CTE zostały stworzone IMO: P – xQbert