SQL - 从上面的行返回值

时间:2013-08-08 10:36:48

标签: sql sql-server database sql-server-2008 tsql

我有一张表:

Book        ¦Time Out       ¦Time In 
123456789   ¦01/01/2013 ¦07/07/2013
123456788   ¦15/01/2013 ¦20/01/2013
123456788   ¦23/01/2013 ¦30/01/2013
123144563   ¦01/02/2013 ¦18/02/2013
123144563   ¦20/02/2013 ¦NULL
124567892   ¦03/03/2013 ¦10/03/2013

我希望它看起来像这样:

Book        ¦Time Out       ¦Time In        ¦Next Time Out
123456789   ¦01/01/2013     ¦07/07/2013     ¦NULL
123456788   ¦15/01/2013     ¦20/01/2013     ¦23/01/2013
123456788   ¦23/01/2013     ¦30/01/2013     ¦NULL
123144563   ¦01/02/2013     ¦18/02/2013     ¦20/02/2013
123144563   ¦20/02/2013     ¦NULL           ¦NULL
124567892   ¦03/03/2013     ¦10/03/2013     ¦NULL

代码:

SELECT nextout.Book,
       nextout.[Time In] AS NextTimeIn
FROM   BookTable nextout
       JOIN BookTable nextoutsec
         ON nextout.Book = nextoutsec.Book
WHERE  nextout.[Time In] = (SELECT MAX(maxtbl.[Time In])
                            FROM   BookTable maxtbl
                            WHERE  maxtbl.Book = nextout.Book) 

这将为重复的图书ID返回相同的“下一次超时”。而不是1个正确的值和1个空值。

谢谢!

4 个答案:

答案 0 :(得分:5)

未经测试,但以下内容应该让您入门

;WITH q as (
  SELECT Book, [Time In], ROW_NUMBER() OVER (PARTITION BY Book ORDER BY [Time In]) AS rn
  FROM   BookTable
)
SELECT  bt.*, q2.[Time In] AS NextTimeIn
FROM    BookTable bt
        INNER JOIN q q1 ON q1.Book = bt.Book AND ISNULL(q1.[Time In], 0) = ISNULL(bt.[Time In], 0)
        LEFT OUTER JOIN q q2 ON q2.Book = q1.Book AND q2.rn = q1.rn + 1

这个要点是

  • q为每本书添加一个行号,按[Time In]
  • 排序
  • q2q1加入以获得下一个[Time In]值。
  • q1BookTable加入以获取所有原始值

答案 1 :(得分:0)

使用OUTER APPLY:

SELECT BT.*, BT2.TimeOut NextTimeOut
    FROM BookTable BT
    OUTER APPLY (
                 SELECT TOP 1 BT2.TimeOut 
                     FROM BookTable BT2 
                     WHERE BT.Book = BT2.Book AND 
                           BT2.TimeOut >= BT.TimeIn 
                     ORDER BY BT2.TimeOut ASC
                ) BT2

SQLFiddle:http://sqlfiddle.com/#!3/67ff0/3

我不确定:

BT2.TimeOut >= BT.TimeIn 
也许它应该是

BT2.TimeOut >= BT.TimeOut

如果同一天有多个TimeIn / TimeOut,它可能会中断(因为您只注册日期,而不是时间)。如果这是一个问题,您可以根据行的id添加比较。

答案 2 :(得分:0)

SQL Fiddle

性能优于CTE。

<强>查询

select [Book]
       ,[TimeOut]
       ,[TimeIn]
       ,NextTimeOut= case 
        when [TimeOut]= NextTimeOut then Null
             else NextTimeOut
        end 
        from

          (select [Book], [TimeOut], [TimeIn]
                ,(select  
                       max(Timeout) from BookTable B1
                       where B1.Book=B2.Book
                 ) NextTimeOut


          from BookTable B2)a

<强> Result

|      BOOK |    TIMEOUT |     TIMEIN | NEXTTIMEOUT |
-----------------------------------------------------
| 123456789 | 01/01/2013 | 07/07/2013 |      (null) |
| 123456788 | 15/01/2013 | 20/01/2013 |  23/01/2013 |
| 123456788 | 23/01/2013 | 30/01/2013 |      (null) |
| 123144563 | 01/02/2013 | 18/02/2013 |  20/02/2013 |
| 123144563 | 20/02/2013 |     (null) |      (null) |
| 124567892 | 03/03/2013 | 10/03/2013 |      (null) |

答案 3 :(得分:0)

您还可以使用相关聚合子查询:

SELECT
  this.Book,
  this.[Time Out],
  this.[Time In],
  [Next Time Out] = (
    SELECT MIN(next.[Time Out])
    FROM BookTable next
    WHERE next.Book = this.Book
      AND next.[Time Out] > this.[Time Out]
  )
FROM BookTable this
;

这可以被视为@xanatos's suggestion的变体,但可能会变得更轻量级。