连接中的计算不起作用?

时间:2012-05-22 16:40:03

标签: 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 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日没有数据时,插入的值应该是-17th.Value(因为一般计算是18th.Value - 17th.Value和18th.Value将为零)。

如果我在插入部分下面放置一个select语句(用于调试),这显示正确,但是,当我删除SELECT语句并在SET部分中进行计算时,它不起作用。我最终得到了Change of null的值,其中找不到5月18日的匹配。

编辑:我应该补充一点,我不确定是否需要LEFT JOIN或LEFT OUTER JOIN。我希望从tab1返回所有行,如果tab2中不存在,则Change值应为-tab1.Value,而不是tab2.Value - tab1.Value。

1 个答案:

答案 0 :(得分:0)

DB2不允许UPDATE s(或DELETE s)包含main table-reference子句中的任何连接,在我看来这会阻止某些类型的问题。是的,我知道你在使用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');

必须按顺序运行 必须 锁定两个语句的组合运行表,还有一些其他方法可以确保不修改包含相关数据的行( INSERT ed,UPDATE d,DELETE d),或者能够分辨触摸的行。

如果这不是您想要的行为,请修改您的问题,以便更清楚您要完成的工作。