Postgresql 9.3 更新连接影响的行数不同于 Select
Postgresql 9.3 Update Join Affects different number of rows than Select
我需要 select 我的 Db 中的一些特定位置,然后更新它们。
尴尬的是,在单独执行 Select
语句时,它 使用 90k 行。
但是在同一个 Select 上执行 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 行(嵌套的 Select 是相同的)
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 分支(未与父分支合并)生成的,但对我来说似乎很正常....
或许不是?
您的查询没问题。我认为您只是发现 (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;
编辑:
糟糕。我怀疑以上是正确的想法,只是错误的列。试试 运行ning 这个版本(你的原始查询聚合):
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
语句中仅更新一次(因此同一对仅更新一次)。
您没有使用子查询中的任何值来执行更新,您只是检查记录是否跨越"dateCreated" 存在 并且(可能)使用 constant/literal 值更新它。
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'
) ;
我需要 select 我的 Db 中的一些特定位置,然后更新它们。
尴尬的是,在单独执行 Select
语句时,它 使用 90k 行。
但是在同一个 Select 上执行 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 行(嵌套的 Select 是相同的)
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 分支(未与父分支合并)生成的,但对我来说似乎很正常....
或许不是?
您的查询没问题。我认为您只是发现 (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;
编辑:
糟糕。我怀疑以上是正确的想法,只是错误的列。试试 运行ning 这个版本(你的原始查询聚合):
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
语句中仅更新一次(因此同一对仅更新一次)。
您没有使用子查询中的任何值来执行更新,您只是检查记录是否跨越"dateCreated" 存在 并且(可能)使用 constant/literal 值更新它。
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'
) ;