Postgresql 9.3 Update Join影响与Select不同的行数

时间:2016-02-17 09:38:09

标签: sql postgresql postgresql-9.3

我需要从我的Db中选择一些特定位置然后更新它们。

尴尬的是,在自己执行Select语句时,使用90k 行。 但是在同一个选项上执行Update语句时,会影响80k 行。

这会产生90k行。

SELECT
    "Extent2"."AppId",
    "Extent2"."DateCreated"
FROM
    "dbo"."Route" AS "Extent1"
    INNER JOIN
    "dbo"."Positions" AS "Extent2" ON
        "Extent1"."BoundAppId" = "Extent2"."AppId" AND
        "Extent2"."DateCreated" > "Extent1"."TimeStarted" AND
        "Extent2"."DateCreated" < "Extent1"."TimeFinished"
WHERE
    "Extent1"."TimeStarted" IS NOT NULL AND
    "Extent1"."TimeFinished" IS NOT NULL AND
    FALSE = "Extent1"."IsDeleted" AND
    "Extent1"."TimeFinished" < '2016-02-06'

这会影响80k行(嵌套选择是相同的)

UPDATE "dbo"."Positions" AS j0
SET "ArchiveUntil" = '2020-02-16'
FROM (
    SELECT
        "Extent2"."AppId",
        "Extent2"."DateCreated"
    FROM
        "dbo"."Route" AS "Extent1"
        INNER JOIN
        "dbo"."Positions" AS "Extent2" ON
            "Extent1"."BoundAppId" = "Extent2"."AppId" AND
            "Extent2"."DateCreated" > "Extent1"."TimeStarted" AND
            "Extent2"."DateCreated" < "Extent1"."TimeFinished"
    WHERE
        "Extent1"."TimeStarted" IS NOT NULL AND
        "Extent1"."TimeFinished" IS NOT NULL AND
        FALSE = "Extent1"."IsDeleted" AND
        "Extent1"."TimeFinished" < '2016-02-06'
) as j1
WHERE (j0."AppId" = j1."AppId" AND j0."DateCreated" = j1."DateCreated")

此SQL是从EntityFramework.Extended Library Source Commit分支生成的(不与父项合并)但对我来说似乎是理智的....

或许不是吗?

2 个答案:

答案 0 :(得分:1)

您的查询没问题。我想您已经发现(AppId, DateCreated)Positions中不是唯一的,或者其中一个值是NULL

您可以运行此查询以验证计数:

select appid, DateCreated, count(*)
from dbo.Positions
group by appid, DateCreated
having count(*) > 1;

某些值也可能是NULL,您可以使用以下内容找到:

select p.*
from dbo.Positions p
where appid is null or DateCreated is null;

编辑:

糟糕。我怀疑以上是正确的想法,只是错误的列。尝试运行此版本(带聚合的原始查询):

SELECT "Extent2"."AppId", "Extent2"."DateCreated", COUNT(*) as cnt
FROM
    "dbo"."Route" AS "Extent1"
    INNER JOIN
    "dbo"."Positions" AS "Extent2" ON
        "Extent1"."BoundAppId" = "Extent2"."AppId" AND
        "Extent2"."DateCreated" > "Extent1"."TimeStarted" AND
        "Extent2"."DateCreated" < "Extent1"."TimeFinished"
WHERE
    "Extent1"."TimeStarted" IS NOT NULL AND
    "Extent1"."TimeFinished" IS NOT NULL AND
    FALSE = "Extent1"."IsDeleted" AND
    "Extent1"."TimeFinished" < '2016-02-06'
GROUP BY "Extent2"."AppId", "Extent2"."DateCreated"
HAVING COUNT(*) >= 2;

我猜这是返回重复项(因此一对值被计算两次)。但是,一行只在update语句中更新一次(因此同一对只更新一次)。

答案 1 :(得分:1)

您不是使用子查询中的任何值到执行更新,您只是检查记录是否跨越&#34; dateCreated&#34; 存在并且(可能)使用常量/文字值更新它。

UPDATE "dbo"."Positions" dst
SET "ArchiveUntil" = '2020-02-16'
WHERE EXISTS (
    SELECT 1
    FROM "dbo"."Route" src
    WHERE dst."BoundAppId" = src."AppId" 
      AND dst."DateCreated" > src."TimeStarted"
      AND dst."DateCreated" < src."TimeFinished"

      -- the two conditions below are redundant
      -- AND src."TimeStarted" IS NOT NULL
      -- AND src."TimeFinished" IS NOT NULL
      AND src."IsDeleted" <> True
      AND src."TimeFinished" < '2016-02-06'
        ) ;