SQL查询获取下一个第5行的值而不使用SQL Server 2008中的while循环或游标

时间:2014-04-06 17:36:04

标签: sql-server sql-server-2008

我正在查询我需要下一行的第n行。我的表结构就像

ID    StockName StockDate   DayOpen DayHigh DayLow  DayClose
--------------------------------------------------------------------
  60    IDBI    2014-01-01  66.50   67.80   66.50   67.60
 197    IDBI    2014-01-02  67.55   69.20   65.25   65.60
 334    IDBI    2014-01-03  65.00   66.40   64.35   66.15
 471    IDBI    2014-01-06  66.15   66.35   65.10   65.55
 608    IDBI    2014-01-07  66.10   66.15   63.85   64.25
 745    IDBI    2014-01-08  64.00   67.10   63.10   66.80
 882    IDBI    2014-01-09  66.60   67.80   64.50   64.75
1019    IDBI    2014-01-10  65.00   65.90   63.75   64.10
1156    IDBI    2014-01-13  63.85   65.00   63.25   64.20
1293    IDBI    2014-01-14  64.00   64.95   63.80   64.05

我想要输出的是列名,它将为我提供下一个第5行日期

E.g。对于第1行,新列应该返回下一个第5行日期的值,即2014-01-08对于第2行应该返回2014-01-09日期。

由于这些是工作日数据,不包括周末,我无法使用datediff -5天计数

如何在不使用while循环或游标的情况下获取此值?

4 个答案:

答案 0 :(得分:3)

使用CTE返回基表加上ROW_NUMBER,以便您可以在新[Next5thDate]列的ROW_NUMBER上将CTE LEFT JOIN连接到当前行的前5行:

SET NOCOUNT ON;
SET ANSI_NULLS ON;

DECLARE @Data TABLE (
                     ID INT NOT NULL PRIMARY KEY CLUSTERED,
                     StockName VARCHAR(50) NOT NULL,
                     StockDate DATE NOT NULL,
                     DayOpen MONEY NOT NULL,
                     DayHigh MONEY NOT NULL,
                     DayLow MONEY NOT NULL,
                     DayClose MONEY NOT NULL,
                     UNIQUE(StockDate)
                    )

INSERT INTO @Data VALUES (60, 'IDBI', '2014-01-01', 66.50, 67.80, 66.50, 67.60)
INSERT INTO @Data VALUES (197, 'IDBI', '2014-01-02', 67.55, 69.20, 65.25, 65.60)
INSERT INTO @Data VALUES (334, 'IDBI', '2014-01-03', 65.00, 66.40, 64.35, 66.15)
INSERT INTO @Data VALUES (471, 'IDBI', '2014-01-06', 66.15, 66.35, 65.10, 65.55)
INSERT INTO @Data VALUES (608, 'IDBI', '2014-01-07', 66.10, 66.15, 63.85, 64.25)
INSERT INTO @Data VALUES (745, 'IDBI', '2014-01-08', 64.00, 67.10, 63.10, 66.80)
INSERT INTO @Data VALUES (882, 'IDBI', '2014-01-09', 66.60, 67.80, 64.50, 64.75)
INSERT INTO @Data VALUES (1019, 'IDBI', '2014-01-10', 65.00, 65.90, 63.75, 64.10)
INSERT INTO @Data VALUES (1156, 'IDBI', '2014-01-13', 63.85, 65.00, 63.25, 64.20)
INSERT INTO @Data VALUES (1293, 'IDBI', '2014-01-14', 64.00, 64.95, 63.80, 64.05)

;WITH cte AS
(
    SELECT  d.*, ROW_NUMBER() OVER (ORDER BY d.StockDate ASC) AS [RowNum]
    FROM    @Data d
)
SELECT d1.ID, d1.StockName, d1.StockDate, d1.DayOpen, d1.DayHigh,
       d1.DayLow, d1.DayClose, d2.StockDate AS [Next5thDate]
FROM cte d1
LEFT JOIN cte d2
       ON d2.RowNum = (d1.RowNum + 5)

结果:

ID  StockName  StockDate    DayOpen DayHigh DayLow  DayClose   Next5thDate
60    IDBI     2014-01-01   66.50   67.80   66.50   67.60      2014-01-08
197   IDBI     2014-01-02   67.55   69.20   65.25   65.60      2014-01-09
334   IDBI     2014-01-03   65.00   66.40   64.35   66.15      2014-01-10
471   IDBI     2014-01-06   66.15   66.35   65.10   65.55      2014-01-13
608   IDBI     2014-01-07   66.10   66.15   63.85   64.25      2014-01-14
745   IDBI     2014-01-08   64.00   67.10   63.10   66.80      NULL
882   IDBI     2014-01-09   66.60   67.80   64.50   64.75      NULL
1019  IDBI     2014-01-10   65.00   65.90   63.75   64.10      NULL
1156  IDBI     2014-01-13   63.85   65.00   63.25   64.20      NULL
1293  IDBI     2014-01-14   64.00   64.95   63.80   64.05      NULL

答案 1 :(得分:1)

With RnkedItems As
    (
    Select Id, StockName, StockDate, DayOpen, DayHigh, DayLow, DayClose
        , Row_Number() Over ( Order By StockDate, Id ) As Rnk
    From MyTable
    )
Select ...
From RnkedItems As Original
    Left Join RnkedItems
        On RnkedItems.Rnk = Original.Rnk + 5

我假设你想要在同一行的目标行之后返回目标行和第五行。

答案 2 :(得分:0)

试试这个:

;with EnumeratedStocks as (
    select rn = row_number() over(order by StockDate), * 
    from Stocks
)
select * from EnumeratedStocks es where rn > 5

答案 3 :(得分:0)

您可以在周末提取下一个日期的第5个日期,方法是将日期从下一个第5天开始提取,如果是星期六,则将日期减去两天以上,如果是星期日,则可以延长一天。

Select * , Case DAYNAME( dateadd(day,5,stockdate))
                When 'Saturday' Then dateadd(day,7,stockdate)
                When 'Sunday' Then dateadd(day,6,stockdate)
           Else dateadd(day,6,stockdate) End As newStockDate
From tableName