【问题标题】:PostgreSQL Inserted rows differ from selectPostgreSQL 插入的行与选择不同
【发布时间】:2016-06-26 21:11:58
【问题描述】:

我在 PostgreSQL 中的 INSERT 有问题。我有这个问题:

INSERT INTO track_segments(tid, gdid1, gdid2, distance, speed)
SELECT * FROM (
SELECT DISTINCT ON (pga.gdid) 
pga.tid as ntid,
pga.gdid as gdid1, pgb.gdid as gdid2,
ST_Distance(pga.geopoint, pgb.geopoint) AS segdist, 
(ST_Distance(pga.geopoint, pgb.geopoint) / EXTRACT(EPOCH FROM (pgb.timestamp - pga.timestamp + interval '0.1 second'))) as speed
FROM fl_pure_geodata AS pga
LEFT OUTER JOIN fl_pure_geodata AS pgb ON (pga.timestamp < pgb.timestamp AND pga.tid = pgb.tid) 
ORDER BY pga.gdid ASC) AS sq
WHERE sq.gdid2 IS NOT NULL;

用成对连接的地理点段填充表格。当我单独运行 SELECT 时,我得到了正确的配对,但是当我在上面的语句中使用它时,有些配对方式错误或根本不配对。这就是我的意思:

单独选择的结果:

tid;gdid1;gdid2;distance;speed
"0f6fd522-5f1e-49a4-b85e-50f11ef7f908";10;11;34.105058803;31.0045989118182
"0f6fd522-5f1e-49a4-b85e-50f11ef7f908";11;12;90.099603143;14.7704267447541
"0f6fd522-5f1e-49a4-b85e-50f11ef7f908";12;13;23.331326565;21.2102968772727

使用相同的 SELECT 插入后的结果:

tid;gdid1;gdid2;distance;speed
"0f6fd522-5f1e-49a4-b85e-50f11ef7f908";10;12;122.574;17.2639603638028
"0f6fd522-5f1e-49a4-b85e-50f11ef7f908";11;12;90.0996;14.7704267447541
"0f6fd522-5f1e-49a4-b85e-50f11ef7f908";12;13;23.3313;21.2102968772727

这是什么原因? INSERT 的 SELECT 语句完全相同,为什么会给出不同的结果?

【问题讨论】:

  • 顺便说一句:WHERE sq.gdid2 IS NOT NULL; 有效地将左连接转换为普通连接。
  • 注 2:(pga.timestamp &lt; pgb.timestamp AND pga.tid = pgb.tid) 连接条件在每个 tid 产生一个 (N*(N-1)/2) 大小的 (partial) carthesian produkt。这就是你想要的吗?
  • @joop 哦,没错。我最初想显示空值,以查看最后一个点是否正确连接到具有不同 tid 的下一个点。我写的时候有点晚了,忘记了 JOIN。谢谢指正!

标签: database postgresql select sql-insert


【解决方案1】:

DISTINCT ON (pga.gdid) 可以从具有相同pga.gdid 的集合中选择任何 行。即使多次执行相同的查询,您也可以获得不同的结果。添加额外的排序以获得一致的结果。类似:pga.gdid ASC, pgb.gdid ASC

顺便说一句,您可能想通过pga.gdid ASC, pgb.timestamp - pga.timestamp ASC 订购以获得“下一个”点。

BTW2 使用lead()lag() 窗口函数来计算当前行和下一个/上一个之间的差异可能更容易。这样您就不需要自我加入,并且可能会获得更好的性能。

【讨论】:

  • 啊,是的!这是有道理的,我希望它有效。旧查询花了 5 秒,现在加上额外的订单,它已经在 2 分钟并且还在计数......
  • “得到正确的结果”通常比“得到一些结果”花费更多的时间。
  • @pfannkuchen_gesicht 查看我的编辑,以获得更好的性能。
  • 刚刚用 Lead()... 和天哪,它只需要原始查询所用时间的 0.3%。
【解决方案2】:

您仅按列 pga.gdid 对查询结果进行排序,该列在所有行中都是相同的,因此每次执行 select 查询时,postgres 都会以不同的方式对结果进行排序。

【讨论】:

  • 什么意思? gdid是连续的,第一列是tid,第二列和第三列是gdid
  • 关于您的编辑:我不是按 pga.tid 订购的。
  • 抱歉,我在接电话。我的意思是,如果您按一列排序并且您有多个具有相同值的结果,那么每次结果的顺序都会不同。
  • 啊,我明白了,我也必须通过 pgb.gdid 订购才能使其正常工作。好的,谢谢!
猜你喜欢
  • 2014-12-19
  • 2011-08-30
  • 2012-10-12
  • 1970-01-01
  • 1970-01-01
  • 2017-04-24
  • 1970-01-01
  • 2011-10-20
相关资源
最近更新 更多