【问题标题】:Access INSERT statement using INNER JOIN with NOT EXISTS gives wrong result使用 INNER JOIN 和 NOT EXISTS 访问 INSERT 语句给出错误结果
【发布时间】:2011-06-27 19:04:25
【问题描述】:

我有一个 Access .mdb 数据库。有两个结构相同的表:Prices 和 tmpPrices。每个表都有三列:[截至日期标准](日期/时间)、价格(双精度)、CUSIP(文本,255 个字符)。 tmpPrices 包含要添加到价格中的新记录。我有两个 SQL 查询来从 tmpPrices 更新价格,一个使用 WHERE 联接,另一个使用 INNER JOIN。

以下版本 A 可以正常工作:

INSERT INTO [Prices] SELECT * FROM [tmpPrices] WHERE NOT EXISTS 
(SELECT * from [Prices]
  WHERE ([Prices].[As of date std] = [tmpPrices].[As of date std])
  AND ([Prices].CUSIP = [tmpPrices].CUSIP));

而此版本 B 不起作用:

INSERT INTO [Prices] SELECT * FROM [tmpPrices] WHERE NOT EXISTS
(SELECT  [Prices].* FROM [Prices] INNER JOIN [tmpPrices] ON 
   ([Prices].[As of Date std] = [tmpPrices].[As of Date std]) 
   AND ([Prices].CUSIP = [tmpPrices].CUSIP));

两个子查询给出相同的结果:来自 tmpPrices 的记录子集已经存在于价格中。

如果不是我必须更新其他表并且使用版本 A 更新另一个表大约需要 45 分钟,但使用版本 B 只是其中的一小部分,并且它似乎可以正常工作,那么使用版本 A 并没有太大关系.所以我想了解这里发生了什么。

【问题讨论】:

    标签: sql ms-access


    【解决方案1】:

    正如@devsh 建议的那样,LEFT JOIN 绝对是要走的路,但您不需要使用子查询。我在 Access 的查询设计器中构建了它,它在 Access 2003 中与您描述的表一起工作。我确实重命名了 [As of date std] 以消除空格。

    INSERT INTO Prices ( As_of_Date_std, Price, CUSIP)
    SELECT t.As_of_Date_std, t.Price, t.CUSIP
    FROM
        tmpPrices AS t
        LEFT JOIN Prices AS p
        ON (t.As_of_Date_std = p.As_of_Date_std) AND (t.CUSIP = p.CUSIP)
    WHERE (((p.As_of_Date_std) Is Null));
    

    【讨论】:

    • 您的解决方案简洁明了,执行速度非常快,即使在有 150 万行的表上也是如此。
    【解决方案2】:

    第二个查询不起作用,因为查询的选择部分(您尝试从中插入)和包含的子查询之间没有链接。如果您确实想使用该格式进行插入,您可以这样做:

    INSERT INTO [Prices]
    SELECT [As of Date], Price, CUSIP
    FROM 
    (SELECT tmpPrices.[As of Date std], tmpPrices.[Price], tmpPrices.[CUSIP]
    FROM tmpPrices LEFT JOIN Prices ON
    ([Prices].[As of date std] = [tmpPrices].[As of date std]) AND ([Prices].CUSIP = [tmpPrices].CUSIP)) WHERE Prices.[As of date std] is null)
    

    【讨论】:

    • 当我尝试运行它时,您的回答给了我一个循环参考。我正在使用 hansup 的解决方案,但我认为 LEFT JOIN 非常聪明。很遗憾,我没有足够的积分来投票。
    【解决方案3】:

    A 需要很长时间,因为它基本上是对价格中的每条记录进行 tmpPrices 的全表扫描,因为在子查询中没有定义实际的连接。

    让我们看看我们能否为您提供快速查询,满足您的需求。

    tmpPrices 需要一个自动编号字段才能工作,我建议将其设置为 tmpPrices 的 pk。还有一个基于其他 3 个字段的唯一键,以防止 tmpPrices 中的重复(很确定您可以在 Access 中做到这一点)。

    INSERT INTO [Prices] ([As of Date std],[Price],[CUSIP])
    SELECT [As of Date std],[Price],[CUSIP] from tmpPrices where autoNumberID not in(
      SELECT autonumberID
      FROM tmpPrices 
      innerJoin prices on [Prices].[As of Date std] = [tmpPrices].[As of Date std] 
       AND [Prices].CUSIP = [tmpPrices].CUSIP
    ) query1
    

    如果您在每次使用此更新价格时清除 tmpPrices 中的任何记录,这也将有助于保持速度。

    【讨论】:

    • 很遗憾,我无法使用您的解决方案,因为我不允许更改表格的结构。
    猜你喜欢
    • 2012-06-05
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 2011-11-28
    • 2017-01-08
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多