需要帮助优化更新语句

时间:2009-12-27 17:02:30

标签: sql sql-server tsql

我有两张桌子:

create table CurrentDay (
ID int identity primary key,
ssn varchar(10), 
val money, 
CheckDate datetime, 
CurrentStatus tinyint)

create table PreviousDay (
ID int identity primary key,
ssn varchar(10), 
val money, 
CheckDate datetime, 
CurrentStatus tinyint)

我需要使用以下值更新字段CurrentDay.CurrentStatus:

  • 111,如果在PreviousDay.ssn中是与CurrentDay中相同的ssn,并且PreviousDay的val与CurrentDay中的相同;
  • 112,如果在PreviousDay.ssn中与CurrentDay相同,并且PreviousDay的val在CurrentDay中更大;
  • 113,如果在PreviousDay.ssn中与CurrentDay相同,并且PreviousDay的val在CurrentDay中更小;
  • 114,如果没有PreviousDay.ssn与CurrentDay相同,即仅在CurrentDay中的ssn(这是今天的信息)。

我写了一些查询,但我希望在PreviousDay和CurrentDay表之间只使用一个连接来找到执行此任务的其他方法。显然,这不是一个非常幸运的类型......这是我的变体:

Update CurrentDay 
Set CurrentStatus=case
when exists (select PreviousDay.ID from PreviousDay 
where PreviousDay.ssn=CurrentDay.ssn AND 
PreviousDay.val=CurrentDay.val  AND
PreviousDay.CheckDate=DATEADD(day,-1,CurrentDay.CheckDate))
then 111
when exists (select PreviousDay.ID from PreviousDay 
where PreviousDay.ssn=CurrentDay.ssn AND 
PreviousDay.val>CurrentDay.val  AND
PreviousDay.CheckDate=DATEADD(day,-1,CurrentDay.CheckDate))
then 112
when exists (select PreviousDay.ID from PreviousDay 
where PreviousDay.ssn=CurrentDay.ssn AND 
PreviousDay.val<CurrentDay.val  AND
PreviousDay.CheckDate=DATEADD(day,-1,CurrentDay.CheckDate))
then 113
when exists (select PreviousDay.ID from PreviousDay 
where PreviousDay.ssn!=CurrentDay.ssn AND 
PreviousDay.CheckDate=DATEADD(day,-1,CurrentDay.CheckDate))
then 114
end;

这是其他查询,但在这种情况下,我无法使用值114更新CurrentDay.CurrentStatus'fieid,因为在两个表中只有ssn上匹配的行:

Set Currentday.CurrentStatus=(select 111 where PreviousDay.val=CurrentDay.val union all select 112 where and PreviousDay.val>CurrentDay.val union all select 113 where and PreviousDay.val<CurrentDay.val /*union all select 114 */ ) from PreviousDay join CurrentDay on PreviousDay.ssn=CurrentDay.ssn and PreviousDay.CheckDate=DATEADD(day,-1,CurrentDay.CheckDate)

你还有其他想法吗?

2 个答案:

答案 0 :(得分:1)

您可以尝试这样的事情

UPDATE CurrentDay 
        SET CurrentStatus =
        CASE 
            WHEN cd.val = pd.val THEN 111
            WHEN cd.val < pd.val THEN 112
            WHEN cd.val > pd.val THEN 113
            WHEN pd.val IS NULL THEN 114
        END
FROM    CurrentDay cd LEFT JOIN
        PreviousDay pd ON   cd.ssn = pd.ssn
                        AND cd.CheckDate = DATEADD(d, 1, pd.CheckDate)

这是我的测试代码。使用PreviousDay的 val 条目来查看它是否有效,或者完全删除PreviousDay的条目以查看新的Entry选项。

DECLARE  @CurrentDay table (
ID int identity primary key,
ssn varchar(10), 
val money, 
CheckDate datetime, 
CurrentStatus tinyint)



DECLARE @PreviousDay table (
ID int identity primary key,
ssn varchar(10), 
val money, 
CheckDate datetime, 
CurrentStatus tinyint)

INSERT INTO @CurrentDay (ssn, val, CheckDate)  SELECT 1, 1, '02 Jan 2009'
INSERT INTO @PreviousDay (ssn, val, CheckDate)  SELECT 1, 0, '01 Jan 2009'

UPDATE @CurrentDay 
        SET CurrentStatus =
        CASE 
            WHEN cd.val = pd.val THEN 111
            WHEN cd.val < pd.val THEN 112
            WHEN cd.val > pd.val THEN 113
            WHEN pd.val IS NULL THEN 114
        END
FROM    @CurrentDay cd LEFT JOIN
        @PreviousDay pd ON  cd.ssn = pd.ssn
                        AND cd.CheckDate = DATEADD(d, 1, pd.CheckDate)

SELECT * FROM @CurrentDay

答案 1 :(得分:1)

类似的东西:

UPDATE
    C
Set
    CurrentStatus = CASE
            WHEN P.val = C.val THEN 111
            WHEN P.val > C.val THEN 112
            WHEN P.val < C.val THEN 113
            ELSE 114 ---this works because if P.VAL is null, that is no matching row
        END
FROM
    CurrentDay C
    LEFT JOIN
    PreviousDay P On C.ssn = P.ssn AND P.CheckDate = DATEADD(day, -1, C.CheckDate))