通过从表中的所有记录重新排序日期来更新字段

时间:2012-08-28 13:44:14

标签: sql sql-server tsql

目前,我有此记录

InvoiceList表

InvoiceID   StoreCustomerID IssuedDate Amount      IsPenalty   EmployeeID
----------- --------------- ---------- ----------- ----------- -----------
1           13              2007-01-12 244         0           41
2           31              2007-04-05 81          0           34
3           23              2007-01-09 184         0           46
4           28              2007-11-21 231         0           17
5           36              2006-09-19 121         0           22
6           28              2006-10-24 240         0           17
7           15              2006-12-11 193         0           47
8           21              2007-01-15 172         0           4

InvoiceID自动递增。我想要做的是通过增加前一行的日期来更新IssuedDate。我想像这样更新它

InvoiceID   StoreCustomerID IssuedDate Amount      IsPenalty   EmployeeID
----------- --------------- ---------- ----------- ----------- -----------
1           13              2007-01-12 244         0           41
2           31              2007-01-13 81          0           34
3           23              2007-01-14 184         0           46
4           28              2007-01-15 231         0           17
5           36              2007-01-16 121         0           22
6           28              2007-01-17 240         0           17
7           15              2007-01-18 193         0           47
8           21              2007-01-19 172         0           4

目前我有这个选择声明并且运作良好。但是我如何使用它来更新IssuedDate

WITH SequenceDate AS
(
    SELECT  *, ROW_NUMBER() OVER (ORDER BY IssuedDate) RowNumber
    FROM    Invoice
)
SELECT RowNumber, DATEADD(d, RowNumber - 1, b.IssuedDate)
FROM SequenceDate
ORDER BY RowNumber

更新1

对于第一篇文章,我非常抱歉,因为给我的指示不正确。日期不应增加,因为我们不允许更改表中的记录,除非我们只能按升序重新排列日期。应该是。

InvoiceID   StoreCustomerID IssuedDate Amount      IsPenalty   EmployeeID
----------- --------------- ---------- ----------- ----------- -----------
1           13              2006-09-19 244         0           41
2           31              2006-10-24 81          0           34
3           23              2006-12-11 184         0           46
4           28              2007-01-09 231         0           17
5           36              2007-01-12 121         0           22
6           28              2007-01-15 240         0           17
7           15              2007-04-05 193         0           47
8           21              2007-11-21 172         0           4

6 个答案:

答案 0 :(得分:7)

如果你知道序列中的第一个日期,你可以简单地将Row_Number添加到int:

; WITH SequenceDate AS
(
    SELECT  *, 
            ROW_NUMBER() OVER (ORDER BY IssuedDate) RowNumber,
            MIN(IssuedDate) over () FirstDate
    FROM    Invoice
)
UPDATE SequenceDate
   SET IssuedDate = DATEADD(d, RowNumber - 1, FirstDate)

Here is Sql Fiddle with example

<强>更新

to match first question's output exactly

; WITH SequenceDate AS
(
    SELECT  *, 
            ROW_NUMBER() OVER (ORDER BY InvoiceID) RowNumber
    FROM    Invoice
)
UPDATE SequenceDate
   SET IssuedDate = DATEADD(d, RowNumber - 1, 
                           (select IssuedDate
                              from Invoice
                             where InvoiceID = 1))

And to rearange dates to follow InvoiceID

; WITH SequenceDate AS
(
    SELECT  *, 
            ROW_NUMBER() OVER (ORDER BY InvoiceID) RowNumber,
            ROW_NUMBER() OVER (ORDER BY IssuedDate) DateNumber
    FROM    Invoice
)
UPDATE SequenceDate
   SET IssuedDate = d.IssuedDate
  from SequenceDate d
 where SequenceDate.RowNumber = d.DateNumber

答案 1 :(得分:3)

首先,您要使用第一个插入日期而不是最小值,然后您应该尝试这样的事情:

    WITH SequenceDate AS
    (
        SELECT  InvoiceID, ROW_NUMBER() OVER (ORDER BY IssuedDate) AS RowNumber
        FROM    Invoice
    )
    UPDATE InvoiceList 
    SET InvoiceList.IssuedDate = DATEADD(d, SequenceDate.RowNumber - 1, b.IssuedDate)   
    FROM SequenceDate 
    INNER JOIN InvoiceList ON SequenceDate.InvoiceID = InvoiceList.InvoiceID 
    CROSS JOIN (SELECT IssuedDate    
                FROM InvoiceList
WHERE InvoiceID = 1) b

SQL Fiddle已附上。

答案 2 :(得分:2)

您可以直接从Invoice加入SequenceDate表。

WITH SequenceDate AS
(
    SELECT  *, ROW_NUMBER() OVER (ORDER BY IssuedDate) RowNumber
    FROM    Invoice
)
UPDATE Invoice 
SET [IssuedDate] = DATEADD(d, RowNumber - 1, b.IssuedDate)
FROM Invoice a INNER JOIN [SequenceDate] b
        ON a.[InvoiceID] = b.[RowNumber]

如果是这种情况,那么试试这个

WITH SequenceDate AS
(
    SELECT  *, ROW_NUMBER() OVER (ORDER BY IssuedDate) RowNumber
    FROM    Invoice
)
UPDATE Invoice 
SET [IssuedDate] = b.IssuedDate
FROM Invoice a INNER JOIN [SequenceDate] b
        ON a.[InvoiceID] = b.[RowNumber]

SQLFiddle Demo

答案 3 :(得分:1)

更新:以下是陈旧的答案,答案是根据OP的原始问题做出的:

为了获得正确的输出,这是最短的:http://www.sqlfiddle.com/#!3/6aa22/1

SELECT * FROM INVOICE;

WITH FirstDate AS
(
    SELECT  row_number() over(order by InvoiceID) rn, IssuedDate
    FROM    Invoice
)
,UpdatedDate as
(
    select i.InvoiceID, i.IssuedDate, dateadd(d, row_number() over(order by i.InvoiceID) - 1, fd.IssuedDate) as NewDate
    from invoice i
    join FirstDate fd on fd.rn = 1
)
update UpdatedDate set IssuedDate = NewDate;

select * from Invoice;

输出:

| INVOICEID | STORECUSTOMERID |                     ISSUEDDATE | AMOUNT | ISPENALTY | EMPLOYEEID |
--------------------------------------------------------------------------------------------------
|         1 |              13 | January, 12 2007 08:00:00-0800 |    244 |         0 |         41 |
|         2 |              31 | January, 13 2007 08:00:00-0800 |     81 |         0 |         34 |
|         3 |              23 | January, 14 2007 08:00:00-0800 |    184 |         0 |         46 |
|         4 |              28 | January, 15 2007 08:00:00-0800 |    231 |         0 |         17 |
|         5 |              36 | January, 16 2007 08:00:00-0800 |    121 |         0 |         22 |
|         6 |              28 | January, 17 2007 08:00:00-0800 |    240 |         0 |         17 |
|         7 |              15 | January, 18 2007 08:00:00-0800 |    193 |         0 |         47 |
|         8 |              21 | January, 19 2007 08:00:00-0800 |    172 |         0 |          4 |

答案 4 :(得分:1)

根据OP的更新问题回答:http://sqlfiddle.com/#!3/dba13/22

with SeqInvoice as
(
  select *, row_number() over(order by InvoiceId) rn from invoice
)
,SeqDate as
(
  select *, row_number() over(order by IssuedDate) rn from invoice
)
update SeqInvoice set IssuedDate = sd.IssuedDate
from SeqDate sd
where sd.rn = SeqInvoice.rn;

select * from Invoice;

输出:

| INVOICEID | STORECUSTOMERID |                       ISSUEDDATE | AMOUNT | ISPENALTY | EMPLOYEEID |
----------------------------------------------------------------------------------------------------
|         1 |              13 | September, 19 2006 02:00:00-0700 |    244 |         0 |         41 |
|         2 |              31 |   October, 24 2006 02:00:00-0700 |     81 |         0 |         34 |
|         3 |              23 |  December, 11 2006 01:00:00-0800 |    184 |         0 |         46 |
|         4 |              28 |   January, 09 2007 01:00:00-0800 |    231 |         0 |         17 |
|         5 |              36 |   January, 12 2007 01:00:00-0800 |    121 |         0 |         22 |
|         6 |              28 |   January, 15 2007 01:00:00-0800 |    240 |         0 |         17 |
|         7 |              15 |     April, 05 2007 02:00:00-0700 |    193 |         0 |         47 |
|         8 |              21 |  November, 21 2007 01:00:00-0800 |    172 |         0 |          4 |

<强>更新

这是一种不直接更新CTE的方法,直接更新基表:http://sqlfiddle.com/#!3/dba13/24

with SeqInvoice as
(
select *, row_number() over(order by InvoiceId) rn from invoice
)
,SeqDate as
(
select *, row_number() over(order by IssuedDate) rn from invoice
)
update I set IssuedDate = sd.IssuedDate
from Invoice i
join SeqInvoice si on si.InvoiceId = i.InvoiceId
join SeqDate sd on sd.rn = si.rn;

select * from Invoice;

答案 5 :(得分:0)

我会使用SQL游标,就像这样......

DECLARE @InvoiceId AS INT
DECLARE @PreviousInvoiceId AS INT
DECLARE @NextIssuedDate AS DATE

SET @PreviousInvoiceId = 0
--Date you want to start from
SET @NextIssuedDate = '2007-01-12'

DECLARE csrUpdateDate CURSOR FOR 

    SELECT InvoiceID FROM Invoice
    ORDER BY InvoiceID

OPEN csrUpdateDate 

FETCH NEXT FROM csrUpdateDate 
INTO @InvoiceId

WHILE @@FETCH_STATUS = 0
BEGIN

    BEGIN 

        IF(@InvoiceId <> @PreviousInvoiceId)

        UPDATE Invoice
        SET IssuedDate = @NextIssuedDate
        WHERE InvoiceId = @InvoiceId

    END

     SET @PreviousInvoiceId = @InvoiceId
     SET @NextIssuedDate = DATEADD(DAY,1,@NextIssuedDate)

    FETCH NEXT FROM csrUpdateDate 
        INTO @InvoiceId

END
CLOSE csrUpdateDate 
DEALLOCATE csrUpdateDate