sql case when newValue else previousValue
sql case when newValue else previousValue
我正在尝试从 Select 创建一个更新,其中在特定情况下 (88) 应该使用先前的值来更新列字段
UPDATE myTable
SET MyDateCol = CASE MYSelect.Indicator
WHEN 88 THEN @previosValue
ELSE MYSelect.NewValue
FROM myTable
INNER JOIN ( ... ) AS MYSelect
ON myTable.ID = MYSelect.ID
示例:
MYSelect | myTable
|
Indicator NewValue | MyDateCol
0 1 | 1
1 2 | 2
88 3 | 2 <-
3 4 | 4
4 5 | 5
5 6 | 6
6 7 | 7
88 8 | 7 <-
完整更新
UPDATE [dbo].[BestellDetails]
SET [Datum] = CASE MYTABLE.WochenTag WHEN 88 THEN lag(MyDate) over(order by MYTABLE.MyDate) ELSE MyDate END
FROM [BestellDetails]
INNER JOIN
(
SELECT INNERTabelle.BestellDetailId,INNERTabelle.WochenTag, DATEADD (dd,INNERTabelle.WochenTag, INNERTabelle.NewDatum) AS MyDate
FROM
(
SELECT TOP 100 PERCENT BestellDetailId,
dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr,
dbo.Bestellung.Kalenderwoche) AS NewDatum,
(CASE BestellDetails.RefMenuId WHEN Speiseplandetails.RefMoId THEN 0
WHEN Speiseplandetails.RefDiId THEN 1
WHEN Speiseplandetails.RefMiId THEN 2
WHEN Speiseplandetails.RefDoId THEN 3
WHEN Speiseplandetails.RefFrId THEN 4
WHEN Speiseplandetails.RefSaId THEN 5
WHEN Speiseplandetails.RefSoId THEN 6 ELSE 88 END) AS WochenTag
FROM dbo.Speiseplandetails
RIGHT OUTER JOIN dbo.BestellDetails ON dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefMoId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefDiId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefMiId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefDoId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefFrId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefSaId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefSoId
RIGHT OUTER JOIN dbo.Bestellung ON dbo.BestellDetails.RefBestellId = dbo.Bestellung.BestellId
order by BestellDetailId
) as INNERTabelle
) AS MYTABLE
ON [BestellDetails].BestellDetailId = MYTABLE.BestellDetailId
UPDATE myTable
SET MyDateCol = CASE MYSelect.Indicator
WHEN 88 THEN (select lag(newvalue) over(order by newvalue) from MySelect) -- @previosValue
ELSE MYSelect.NewValue
FROM myTable
INNER JOIN ( ... ) AS MYSelect
ON myTable.ID = MYSelect.ID
这是假设必须根据 newvalue
列中的升序选择先前的值。
lag()
应该做你想做的。你可以直接把它放在 MySelect
定义中。或者使用子查询:
WITH myselect as (
. . .
)
UPDATE myTable
SET MyDateCol = (CASE MYSelect.Indicator
WHEN 88 THEN MYSelecct.prevvalue
ELSE MYSelect.NewValue
END
FROM myTable INNER JOIN
(SELECT myselect.*, lag(newvalue) over (order by newvalue) as prevvalue
FROM myselect
) myselect
ON myTable.ID = MYSelect.ID;
请尝试以下查询。
它优化了您的查询,还处理了重复 88
值的情况。就我而言,我使用 NULL
而不是 88
.
Can we have two rows in succession that both have an 88 indicator? –
Damien_The_Unbeliever
CREATE TABLE #temp(
BestellDetailId int, row_num int,MyDate date
)
INSERT INTO #temp
SELECT TOP 100 PERCENT
BestellDetailId,
ROW_NUMBER() OVER (order by BestellDetailId) as row_num,
(
CASE BestellDetails.RefMenuId
WHEN Speiseplandetails.RefMoId THEN DATEADD (dd,0, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
WHEN Speiseplandetails.RefDiId THEN DATEADD (dd,1, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
WHEN Speiseplandetails.RefMiId THEN DATEADD (dd,2, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
WHEN Speiseplandetails.RefDoId THEN DATEADD (dd,3, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
WHEN Speiseplandetails.RefFrId THEN DATEADD (dd,4, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
WHEN Speiseplandetails.RefSaId THEN DATEADD (dd,5, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
WHEN Speiseplandetails.RefSoId THEN DATEADD (dd,6, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
ELSE NULL END
) AS MyDate
FROM dbo.Speiseplandetails
RIGHT OUTER JOIN dbo.BestellDetails ON dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefMoId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefDiId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefMiId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefDoId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefFrId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefSaId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefSoId
RIGHT OUTER JOIN dbo.Bestellung ON dbo.BestellDetails.RefBestellId = dbo.Bestellung.BestellId
order by BestellDetailId
--updating the temp table with correct values
update t1
set t1.myDate=t3.myDate
from #temp t1 left join #temp t3
on t3.row_num in
(select max(row_num) from #temp t2 where t2.myDate is not null and t2.row_num<t1.row_num)
where t1.MyDate is NULL
UPDATE [dbo].[BestellDetails]
SET [Datum] = MYTABLE.myDate
FROM [BestellDetails]
INNER JOIN
#temp AS MYTABLE
ON [BestellDetails].BestellDetailId = MYTABLE.BestellDetailId
下面是使用最后一个值更新 table 的示例 fiddle
http://sqlfiddle.com/#!6/c78ae/8
我正在尝试从 Select 创建一个更新,其中在特定情况下 (88) 应该使用先前的值来更新列字段
UPDATE myTable
SET MyDateCol = CASE MYSelect.Indicator
WHEN 88 THEN @previosValue
ELSE MYSelect.NewValue
FROM myTable
INNER JOIN ( ... ) AS MYSelect
ON myTable.ID = MYSelect.ID
示例:
MYSelect | myTable
|
Indicator NewValue | MyDateCol
0 1 | 1
1 2 | 2
88 3 | 2 <-
3 4 | 4
4 5 | 5
5 6 | 6
6 7 | 7
88 8 | 7 <-
完整更新
UPDATE [dbo].[BestellDetails]
SET [Datum] = CASE MYTABLE.WochenTag WHEN 88 THEN lag(MyDate) over(order by MYTABLE.MyDate) ELSE MyDate END
FROM [BestellDetails]
INNER JOIN
(
SELECT INNERTabelle.BestellDetailId,INNERTabelle.WochenTag, DATEADD (dd,INNERTabelle.WochenTag, INNERTabelle.NewDatum) AS MyDate
FROM
(
SELECT TOP 100 PERCENT BestellDetailId,
dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr,
dbo.Bestellung.Kalenderwoche) AS NewDatum,
(CASE BestellDetails.RefMenuId WHEN Speiseplandetails.RefMoId THEN 0
WHEN Speiseplandetails.RefDiId THEN 1
WHEN Speiseplandetails.RefMiId THEN 2
WHEN Speiseplandetails.RefDoId THEN 3
WHEN Speiseplandetails.RefFrId THEN 4
WHEN Speiseplandetails.RefSaId THEN 5
WHEN Speiseplandetails.RefSoId THEN 6 ELSE 88 END) AS WochenTag
FROM dbo.Speiseplandetails
RIGHT OUTER JOIN dbo.BestellDetails ON dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefMoId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefDiId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefMiId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefDoId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefFrId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefSaId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefSoId
RIGHT OUTER JOIN dbo.Bestellung ON dbo.BestellDetails.RefBestellId = dbo.Bestellung.BestellId
order by BestellDetailId
) as INNERTabelle
) AS MYTABLE
ON [BestellDetails].BestellDetailId = MYTABLE.BestellDetailId
UPDATE myTable
SET MyDateCol = CASE MYSelect.Indicator
WHEN 88 THEN (select lag(newvalue) over(order by newvalue) from MySelect) -- @previosValue
ELSE MYSelect.NewValue
FROM myTable
INNER JOIN ( ... ) AS MYSelect
ON myTable.ID = MYSelect.ID
这是假设必须根据 newvalue
列中的升序选择先前的值。
lag()
应该做你想做的。你可以直接把它放在 MySelect
定义中。或者使用子查询:
WITH myselect as (
. . .
)
UPDATE myTable
SET MyDateCol = (CASE MYSelect.Indicator
WHEN 88 THEN MYSelecct.prevvalue
ELSE MYSelect.NewValue
END
FROM myTable INNER JOIN
(SELECT myselect.*, lag(newvalue) over (order by newvalue) as prevvalue
FROM myselect
) myselect
ON myTable.ID = MYSelect.ID;
请尝试以下查询。
它优化了您的查询,还处理了重复 88
值的情况。就我而言,我使用 NULL
而不是 88
.
Can we have two rows in succession that both have an 88 indicator? – Damien_The_Unbeliever
CREATE TABLE #temp(
BestellDetailId int, row_num int,MyDate date
)
INSERT INTO #temp
SELECT TOP 100 PERCENT
BestellDetailId,
ROW_NUMBER() OVER (order by BestellDetailId) as row_num,
(
CASE BestellDetails.RefMenuId
WHEN Speiseplandetails.RefMoId THEN DATEADD (dd,0, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
WHEN Speiseplandetails.RefDiId THEN DATEADD (dd,1, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
WHEN Speiseplandetails.RefMiId THEN DATEADD (dd,2, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
WHEN Speiseplandetails.RefDoId THEN DATEADD (dd,3, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
WHEN Speiseplandetails.RefFrId THEN DATEADD (dd,4, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
WHEN Speiseplandetails.RefSaId THEN DATEADD (dd,5, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
WHEN Speiseplandetails.RefSoId THEN DATEADD (dd,6, dbo.FirstDateOfWeekISO8601(dbo.Bestellung.Jahr, dbo.Bestellung.Kalenderwoche) )
ELSE NULL END
) AS MyDate
FROM dbo.Speiseplandetails
RIGHT OUTER JOIN dbo.BestellDetails ON dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefMoId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefDiId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefMiId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefDoId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefFrId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefSaId
OR dbo.BestellDetails.RefMenuId = dbo.Speiseplandetails.RefSoId
RIGHT OUTER JOIN dbo.Bestellung ON dbo.BestellDetails.RefBestellId = dbo.Bestellung.BestellId
order by BestellDetailId
--updating the temp table with correct values
update t1
set t1.myDate=t3.myDate
from #temp t1 left join #temp t3
on t3.row_num in
(select max(row_num) from #temp t2 where t2.myDate is not null and t2.row_num<t1.row_num)
where t1.MyDate is NULL
UPDATE [dbo].[BestellDetails]
SET [Datum] = MYTABLE.myDate
FROM [BestellDetails]
INNER JOIN
#temp AS MYTABLE
ON [BestellDetails].BestellDetailId = MYTABLE.BestellDetailId
下面是使用最后一个值更新 table 的示例 fiddle http://sqlfiddle.com/#!6/c78ae/8