使用'SELECT TOP'生成WHERE的参数列表

时间:2013-05-23 16:04:39

标签: sql azure-sql-database

我有一张这样的表:

|    date   | example_variable |
| 2013-2-22 |       cat        |
| 2013-3-22 |       dog        |
| 2013-1-22 |       ewe        |
| 2013-8-22 |       pig        |

我已经知道该怎么做:

SELECT
a.example_variable as V1,
b.example_variable as V2,
c.example_variable as V3, 
a.AsOfDate as 1stDate,     
b.AsOfDate as 2ndDate,
c.AsOfDate as 3rdDate
FROM <table> a, <table> b, <table> c
WHERE a.AsOfDate = '2013-1-22'
AND b.AsOfDate = '2013-2-22'
AND c.AsOfDate = '2013-3-22'

输出如:

|   V1   |   V2   |   V3   |    1stDate   |    2ndDate   |    3rdDate   |
|  ewe   |   cat  |   dog  |  '2013-1-22' |  '2013-2-22' | '2013-3-22'  |

在上面的查询中,我手动输入了最近的三个日期。我希望自动找到那些。好像我可以使用top,但我不确定如何。


更复杂的版本:

我简化了上面的例子。在我的真实案例中,有多行具有相同的日期,如下所示:

|    date   |      rank        | example_variable  |
| 2013-2-22 |      1           |       cat1        |
| 2013-2-22 |      2           |       cat2        |
| 2013-3-22 |      1           |       dog1        |
| 2013-3-22 |      2           |       dog2        |
| 2013-1-22 |      1           |       ewe1        |
| 2013-1-22 |      2           |       ewe2        |
| 2013-8-22 |      1           |       pig1        |
| 2013-8-22 |      2           |       pig2        |

查询是这样的:

SELECT
a.rank, b.rank, c.rank,
a.example_variable as V1,
b.example_variable as V2,
c.example_variable as V3, 
a.AsOfDate as 1stDate,     
b.AsOfDate as 2ndDate,
c.AsOfDate as 3rdDate
FROM <table> a, <table> b, <table> c
WHERE a.rank = b.rank,
And b.rank = c.rank,
AND a.AsOfDate = '2013-1-22'
AND b.AsOfDate = '2013-2-22'
AND c.AsOfDate = '2013-3-22'

输出:

|  rank  |   V1    |   V2    |   V3    |    1stDate   |    2ndDate   |    3rdDate   |
|   1    |  ewe1   |   cat1  |   dog1  |  '2013-1-22' |  '2013-2-22' | '2013-3-22'  |
|   2    |  ewe2   |   cat2  |   dog2  |  '2013-1-22' |  '2013-2-22' | '2013-3-22'  |

1 个答案:

答案 0 :(得分:6)

编辑1:即使您使用更复杂的数据版本,您仍然可以使用row_number()

select [rank],
  max(case when rn = 1 then example_variable end) as v1,
  max(case when rn = 2 then example_variable end) as v2,
  max(case when rn = 3 then example_variable end) as v3,
  max(case when rn = 1 then date end) as [1stDate],
  max(case when rn = 2 then date end) as [2ndDate],
  max(case when rn = 3 then date end) as [3rdDate]
from
(
  select date, [rank], example_variable,
    row_number() over(partition by [rank] order by date) rn
  from yt
) d
group by [rank];

请参阅Demo

如果您没有row_number,则可以使用以下内容:

;with d1 as
(
  select t.date, t.[rank], t.example_variable
  from yt t
  inner join
  (
    select min(date) date, [rank]
    from yt
    group by [rank]
  ) d
    on t.date = d.date
    and t.[rank] = d.[rank]
)
select d1.rank,
  d1.example_variable v1,
  d2.example_variable v2,
  d3.example_variable v3,
  d1.date [1stDate],
  d2.date [2ndDate],
  d3.date [3rdDate]
from d1
cross apply
(
  select top 1 date, [rank], example_variable
  from yt t
  where d1.date < t.date
    and d1.[rank] = t.[rank]
) d2
cross apply
(
  select top 1 date, [rank], example_variable
  from yt t
  where d2.date < t.date
    and d2.[rank] = t.[rank]
) d3;

请参阅Demo

您没有指定正在使用的数据库,但如果您使用的是支持窗口函数的数据库,那么您可以使用row_number()

select 
  max(case when rn = 1 then example_variable end) as v1,
  max(case when rn = 2 then example_variable end) as v2,
  max(case when rn = 3 then example_variable end) as v3,
  max(case when rn = 1 then date end) as [1stDate],
  max(case when rn = 2 then date end) as [2ndDate],
  max(case when rn = 3 then date end) as [3rdDate]
from
(
  select date, example_variable,
    row_number() over(order by date) rn
  from yt
) d;

请参阅SQL Fiddle with Demo

如果您没有row_number,那么您可以使用以下内容:

select d1.example_variable v1,
  d2.example_variable v2,
  d3.example_variable v3,
  d1.date [1stdate],
  d2.date [2nddate],
  d3.date [3rddate]
from
(
  select top 1 date, example_variable
  from yt
  order by date
) d1
cross apply
(
  select top 1 d2.date, d2.example_variable
  from yt d2
  where d1.date < d2.date
  order by d2.date
) d2
cross apply
(
  select top 1 d3.date, d3.example_variable
  from yt d3
  where d2.date < d3.date
  order by d3.date
) d3;

请参阅Demo