2013-02-14 13 views
5

mam poniższej tabeli:SQL Server Pivots ... Mogę pokazać ostatnie pięć zleceń dla szeregu rodzajów zleceń

create table myorders(ordertype char(1), orderdate datetime, orderid int) 

Ta tabela zawiera następujące dane:

insert into myorders(ordertype, orderdate, orderid) values('P', '2013-02-14 20:04:48:287', 11082360) 
insert into myorders(ordertype, orderdate, orderid) values('P', '2013-02-14 20:02:40:407', 40087130) 
insert into myorders(ordertype, orderdate, orderid) values('P', '2013-02-14 20:02:07:277', 7990558) 
insert into myorders(ordertype, orderdate, orderid) values('C', '2013-02-14 19:58:46:097', 8225181) 
insert into myorders(ordertype, orderdate, orderid) values('P', '2013-02-14 19:58:39:740', 40087129) 
insert into myorders(ordertype, orderdate, orderid) values('C', '2013-02-14 19:57:33:063', 8225235) 
insert into myorders(ordertype, orderdate, orderid) values('C', '2013-02-14 19:56:17:207', 8225233) 
insert into myorders(ordertype, orderdate, orderid) values('C', '2013-02-14 19:54:50:630', 8225232) 
insert into myorders(ordertype, orderdate, orderid) values('P', '2013-02-14 19:48:07:300', 11082337) 
insert into myorders(ordertype, orderdate, orderid) values('P', '2013-02-14 19:47:49:997', 40087128) 
insert into myorders(ordertype, orderdate, orderid) values('P', '2013-02-14 19:46:40:667', 40087127) 
insert into myorders(ordertype, orderdate, orderid) values('C', '2013-02-14 19:45:32:550', 8225231) 
insert into myorders(ordertype, orderdate, orderid) values('P', '2013-02-14 19:45:11:203', 11082326) 
insert into myorders(ordertype, orderdate, orderid) values('C', '2013-02-14 19:44:57:990', 8225230) 
insert into myorders(ordertype, orderdate, orderid) values('P', '2013-02-14 19:43:52:953', 40087126) 
insert into myorders(ordertype, orderdate, orderid) values('C', '2013-02-14 19:43:20:853', 8225229) 
insert into myorders(ordertype, orderdate, orderid) values('P', '2013-02-14 19:41:33:740', 11082319) 
insert into myorders(ordertype, orderdate, orderid) values('C', '2013-02-14 19:41:19:853', 8225228) 
insert into myorders(ordertype, orderdate, orderid) values('P', '2013-02-14 19:40:33:127', 40087125) 
insert into myorders(ordertype, orderdate, orderid) values('P', '2013-02-14 19:40:25:537', 40087124) 

dane wygląda następująco:

OrderType OrderDate     OrderId 
-------- -----------------------  --------- 
P  2013-02-14 20:04:48.287 11082360 
P  2013-02-14 20:02:40.407 40087130 
P  2013-02-14 20:02:07.277 7990558 
C  2013-02-14 19:58:46.097 8225181 
P  2013-02-14 19:58:39.740 40087129 
C  2013-02-14 19:57:33.063 8225235 
C  2013-02-14 19:56:17.207 8225233 
C  2013-02-14 19:54:50.630 8225232 
P  2013-02-14 19:48:07.300 11082337 
P  2013-02-14 19:47:49.997 40087128 
P  2013-02-14 19:46:40.667 40087127 
C  2013-02-14 19:45:32.550 8225231 
P  2013-02-14 19:45:11.203 11082326 
C  2013-02-14 19:44:57.990 8225230 
P  2013-02-14 19:43:52.953 40087126 
C   2013-02-14 19:43:20.853 8225229 
P  2013-02-14 19:41:33.740 11082319 
C  2013-02-14 19:41:19.853 8225228 
P  2013-02-14 19:40:33.127 40087125 
P  2013-02-14 19:40:25.537 40087124 

Chciałbym obracać dane więc wygląda to tak:

C_LastFiveOrders C_OrderDate     P_LastFiveOrders P_OrderDate 
---------------- -----------------------  ---------------- ----------------------- 
8225181   2013-02-14 19:58:46.097  11082360   2013-02-14 20:04:48.287 
8225235   2013-02-14 19:57:33.063  40087130   2013-02-14 20:02:40.407 
8225233   2013-02-14 19:56:17.207  7990558   2013-02-14 20:02:07.277 
8225232   2013-02-14 19:54:50.630  40087129   2013-02-14 19:58:39.740 
8225231   2013-02-14 19:45:32.550  11082337   2013-02-14 19:48:07.300 

Należy zauważyć, że zamówienia są sortowane według daty zamówienia w kolejności malejącej.

Chciałbym mieć możliwość dodania kolejnych OrderTypes. Chciałbym również elastyczności, aby spojrzeć na ostatnie x zamówienia. W próbce patrzę na ostatnie pięć zamówień. Chciałbym móc spojrzeć na ostatnie 10 lub 20 zamówień.

+3

+1 Do konfiguracji stołu i danych! – Bryan

+1

-1 za nie próbowanie niczego! – Kermit

+0

Zasłużyłem na to.Zamierzam zostać guru Pivot jak bluefeet. Będą mnie nazywać Pivot Ken LOL. – codingguy3000

Odpowiedz

4

Istnieje kilka różnych sposobów, w jakie można to wykonać.

Kruszywo z CASE: Można użyć funkcji zagregowanego z wyrażeniem CASE:

select 
    max(case when ordertype = 'c' then orderid end) C_LASTFIVEORDERS, 
    max(case when ordertype = 'c' then orderdate end) C_ORDERDATE, 
    max(case when ordertype = 'p' then orderid end) P_LASTFIVEORDERS, 
    max(case when ordertype = 'p' then orderdate end) P_ORDERDATE 
from 
(
    select orderid, ordertype, orderdate, rn 
    from 
    (
    select orderid, ordertype, orderdate, 
     row_number() over(partition by ordertype 
         order by orderdate desc) rn 
    from myorders 
) src 
    where rn <=5 
) s 
group by rn 

Zobacz SQL Fiddle with Demo.

Multiple przyłącza: Możesz dołączyć na stole wiele razy:

;with cte as 
(
    select orderid, ordertype, orderdate, 
     row_number() over(partition by ordertype 
         order by orderdate desc) rn 
    from myorders 
) 
select 
    c1.orderid C_LASTFIVEORDERS, 
    c1.orderdate C_ORDERDATE, 
    c2.orderid P_LASTFIVEORDERS, 
    c2.orderdate P_ORDERDATE 
from cte c1 
left join cte c2 
    on c1.rn = c2.rn 
    and c2.ordertype = 'P' 
where c1.rn <=5 
    and c1.ordertype = 'C' 

Zobacz SQL Fiddle with Demo

Static PIVOT:

Wreszcie, można zastosować zarówno UNPIVOT i tym PIVOT funkcja, aby uzyskać wynik:

select C_LastFiveOrders, C_orderdate, 
    P_LastFiveOrders, P_orderdate 
from 
(
    select rn, 
    case 
     when col = 'orderid' then ordertype+'_LastFiveOrders' 
     else ordertype+'_'+col end col_name, 
    value 
    from 
    (
    select ordertype, 
     convert(varchar(50), orderdate, 121) orderdate, 
     cast(orderid as varchar(50)) orderid, 
     row_number() over(partition by ordertype 
         order by orderdate desc) rn 
    from myorders 
)src 
    unpivot 
    (
    value 
    for col in (orderdate, orderid) 
) un 
    where rn <= 5 
) s 
pivot 
(
    max(value) 
    for col_name in (C_LastFiveOrders, C_orderdate, 
        P_LastFiveOrders, P_orderdate) 
) piv 

Zobacz SQL Fiddle with Demo.

Dynamiczny PIVOT:

Jeśli wartości OrderType nie są znane, to można użyć dynamicznego SQL:

DECLARE @cols AS NVARCHAR(MAX), 
    @colsName AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(ordertype +c.col) 
         from myorders 
         cross apply 
         (
         select '_LastFiveOrders' col 
         union all 
         select '_OrderDate' 
        ) c 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 


set @query 
    = 'SELECT ' + @cols + ' 
    from 
    (
     select rn, 
     case 
      when col = ''orderid'' then ordertype+''_LastFiveOrders'' 
      else ordertype+''_''+col end col_name, 
     value 
     from 
     (
     select ordertype, 
      convert(varchar(50), orderdate, 121) orderdate, 
      cast(orderid as varchar(50)) orderid, 
      row_number() over(partition by ordertype 
          order by orderdate desc) rn 
     from myorders 
    )src 
     unpivot 
     (
     value 
     for col in (orderdate, orderid) 
    ) un 
     where rn <= 5 
    ) s 
    pivot 
    (
     max(value) 
     for col_name in (' + @cols + ') 
    ) p 
    ' 

execute(@query) 

Zobacz SQL Fiddle with Demo

Zapytania daje wynik:

| C_LASTFIVEORDERS |    C_ORDERDATE | P_LASTFIVEORDERS |    P_ORDERDATE | 
------------------------------------------------------------------------------------------- 
|   8225181 | 2013-02-14 19:58:46.097 |   11082360 | 2013-02-14 20:04:48.287 | 
|   8225235 | 2013-02-14 19:57:33.063 |   40087130 | 2013-02-14 20:02:40.407 | 
|   8225233 | 2013-02-14 19:56:17.207 |   7990558 | 2013-02-14 20:02:07.277 | 
|   8225232 | 2013-02-14 19:54:50.630 |   40087129 | 2013-02-14 19:58:39.740 | 
|   8225231 | 2013-02-14 19:45:32.550 |   11082337 | 2013-02-14 19:48:07.300 | 
+0

+1 za zmuszanie mnie do przewijania 3-kołowrotowych obrotów. – Kermit

+0

@njk przepraszam Nie mogę sobie pomóc – Taryn

+0

Wygrywasz, to jedyny problem z wersją dynamiczną sql, że kolumny nie są w porządku. – codingguy3000

2

Może to działać:

;WITH myorders_CTE AS 
    (
    SELECT ordertype, orderdate, orderid, 
    row_number() over (partition BY ordertype ORDER BY orderdate DESC) AS sequence 
    FROM myorders 
) 

SELECT c.orderid AS C_LastFiveOrders, c.orderdate AS C_OrderDate, 
    p.orderid AS P_LastFiveOrders, p.orderdate AS P_OrderDate 
FROM myorders_CTE c 
JOIN myorders_CTE p ON c.sequence = p.sequence 
WHERE c.ordertype = 'C' 
    AND p.ordertype = 'P' 
    AND c.sequence <= 5 
    AND p.sequence <= 5 
ORDER BY c.sequence 

Wykorzystuje samołączenie, ale nie używa PIVOT.

Powiązane problemy