5

我有下表:

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

该表有以下数据:

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)

数据如下所示:

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

我想旋转数据,使其看起来像这样:

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

请注意,订单按 orderdate 降序排列。

我希望能够添加额外的 OrderTypes。我还希望灵活地查看最后 x 个订单。在示例中,我正在查看最后五个订单。我希望能够查看最近的 10 或 20 个订单。

4

2 回答 2

4

有几种不同的方法可以执行此操作。

使用 CASE 聚合:您可以将聚合函数与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

请参阅SQL Fiddle with Demo

多次加入:您可以多次加入您的表:

;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'

请参阅带有演示的 SQL Fiddle

静态枢轴:

最后,您可以同时应用UNPIVOTPIVOT函数来获得结果:

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

请参阅SQL Fiddle with Demo

动态枢轴:

如果您的OrderType值未知,则可以使用动态 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)

请参阅带有演示的 SQL Fiddle

所有查询都会给出结果:

| 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 |
于 2013-02-14T20:47:41.147 回答
2

这可能有效:

;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

它使用自联接,但不使用 PIVOT。

于 2013-02-14T20:49:30.407 回答