Sql 联接中的计算不起作用?

Sql 联接中的计算不起作用?,sql,sql-server,Sql,Sql Server,我有这样的想法: UPDATE Table_Name SET Change = isnull(tab2.Value,0) - tab1.Value FROM (SELECT Date,ID,ID,FileName,Value FROM Table_Name WHERE FileName = 'x' AND Date = '2012-05-17') tab1 LEFT OUTER JOIN (SELECT Date,ID,TradeID,FileName,Value FROM

我有这样的想法:

UPDATE Table_Name
SET Change = isnull(tab2.Value,0) - tab1.Value 
FROM 
    (SELECT Date,ID,ID,FileName,Value FROM Table_Name WHERE FileName = 'x' AND Date = '2012-05-17') tab1
LEFT OUTER JOIN 
    (SELECT Date,ID,TradeID,FileName,Value FROM Table_Name WHERE FileName = 'x' AND Date = '2012-05-18')  tab2 
ON tab1.FileName = tab2.FileName AND 
tab1.ID = tab2.ID  AND 
tab1.ID = tab2.ID
如您所见,它是一个左外连接。但是,当我有5月17日的数据,而没有5月18日的数据时,插入的值应该是-17.value,因为一般的计算是18.value-17.value和18.value将是零

如果我将select语句放在insert部件的正下方以进行调试,这将正确显示,但是,当我删除select语句并在SET部件中进行计算时,它不起作用。我最终得到了null的Change值,其中找不到5月18日的匹配项

编辑:我应该添加我不确定我是否需要左连接或左外连接。我希望返回tab1中的所有行,如果tab2中不存在,则更改值应该是-tab1.value,而不是tab2.value-tab1.value。

DB2不允许在主表引用子句中包含任何连接的更新或删除,我认为这可以防止某些类型的问题。是的,我知道您使用的是SQL Server,这就是您尝试这样做的原因——我只是倾向于在编写时考虑DB2约束,仅此而已

假设您想更新17号的行,我相信下面的方法应该可以。否则,请指定实际需要更新的行

UPDATE Table_Name 
SET change = -value + COALESCE((SELECT nxt.value
                                FROM Table_Name nxt
                                WHERE nxt.fileName = table_name.fileName
                                AND nxt.id = table_name.id
                                AND nxt.scenarioId = table_name.scenarioId
                                AND nxt.cobDate = '2012-05-18'), 0)
WHERE fileName = 'GBP.csv'
AND cobDate = '2012-05-17'
编辑: 更正了上述错误

然而。。。听上去,您可能试图更新不存在的行;具体来说,“需要输入第18次的结果”。如果您正在尝试更新第18行中确实存在的行,或者在不存在的情况下插入这些行,那么您将需要两个语句,或者可能需要一个MERGE?但我的版本中没有,所以我无法帮助您:

UPDATE Table_Name
SET change = value - COALESCE((SELECT prev.value
                               FROM Table_Name prev
                               WHERE prev.fileName = table_name.fileName
                               AND prev.id = table_name.id
                               AND prev.scenarioId = table_name.scenarioId
                               AND prev.cobDate = '2012-05-17'), 0)
WHERE fileName = 'GBP.csv'
AND cobDate = '2012-05-18';

INSERT INTO Table_Name (id, scenarioId, fileName, cobDate, value, change) 
                        SELECT id, scenarioId, fileName, '2012-05-18', 0, -value
                        FROM Table_Name
                        WHERE fileName = 'GBP.csv'
                        AND cobDate = '2012-05-17'
                        AND NOT EXISTS (SELECT '1'
                                        FROM Table_Name nxt
                                        WHERE nxt.fileName = table_name.filename
                                        AND nxt.id = table_name.id
                                        AND nxt.scenarioId = table_name.scenarioId
                                        AND nxt.cobDate = '2012-05-18');
你必须按那个顺序运行它们。 您还必须为这两条语句的组合运行锁定表,使用其他方法确保没有包含相关数据的行被修改、插入、更新、删除,或者能够判断哪些行未被触碰


如果这不是您想要的行为,请修改您的问题,以便更清楚地了解您试图实现的目标。

您正在对第一个值而不是第二个值进行ISNULL检查,这可能是一个问题吗?@PaulMcCowat EXISTS不允许他从该表中提取该值。他在第二个字段中不会有NULL,因为它是源表而不是联接表。在tab2.value为NULL的情况下,计算得到的值是什么?@JNK,如果我在“SET”下面插入另一个级别的SELECT进行调试,并在这个额外的SELECT语句中执行计算,我会得到0而不是NULL——正如我所希望的那样。但是,当我删除select并将计算和null检查转移到SET语句时,它出错了。@user1107474和Table_Name在所有这些语句中的位置?Hi Z-Zero,语法“as origin”和“0”似乎有一个小问题,后者可能是前一个错误的结果?关于错误,这是一个在合并后丢失的括号,我无法让“作为原点”工作。我替换了原点。这张桌子有个名字。我想这不是我想要的。减法的结果实际上需要输入第18个,重点是左连接。我试着编辑你的SQL,但我没能做到:那可能是我的错误!