2017-10-09 79 views
0

有人能指出我在做什么错在这里?SQL左连接表现奇怪

我有时间戳的数据表:

CREATE TABLE data_record (
    id UUID, 
    t TIMESTAMP, 
    d INTEGER, 
    PRIMARY KEY(id, t) 
); 

我已经从该表中的一些项目得到了一些数据,现在我试图创建一个批处理过程中保持一个项目中,数据值(d)是其他项目的总和。首先,我试图插入行的汇总项目在其他项目具有行中的所有时间戳:

WITH source_ids AS (
    SELECT UNNEST(ARRAY['1e77b896-9e1b-11e7-a0db-f23c91e2b423'::uuid, '7dd37dd0-9e1a-11e7-a0db-f23c91e2b423'::uuid]) 
) 
INSERT INTO data_record (id, t) (
    SELECT DISTINCT 'ab3b516e-acd7-11e7-a0db-f23c91e2b423'::uuid, d1.t 
     FROM data_record d1 
    LEFT JOIN data_record d2 
     ON d1.t = d2.t 
     AND d1.id IN (SELECT * FROM source_ids) 
     AND d2.id = 'ab3b516e-acd7-11e7-a0db-f23c91e2b423'::uuid 
     WHERE d2.t IS NULL; 

据我所看到的,应该创建一个ID ab3b516e-acd7-11e7-a0db-f23c91e2b423一排每一个时间戳与source_ids中的任一ID相连。但执行该查询后,我再这样做:

WITH source_ids AS (
    SELECT UNNEST(ARRAY['1e77b896-9e1b-11e7-a0db-f23c91e2b423'::uuid, '7dd37dd0-9e1a-11e7-a0db-f23c91e2b423'::uuid]) 
) 
    SELECT COUNT(d1.t) 
    FROM data_record d1 
LEFT JOIN data_record d2 
     ON d1.t = d2.t 
     AND d1.id IN (SELECT * FROM source_ids) 
     AND d2.id = 'ab3b516e-acd7-11e7-a0db-f23c91e2b423' 
    WHERE d2.t IS NULL; 

INSERT查询受影响的28237行; SELECT查询返回55561,我认为它应该返回零。

我想有一些关于AND d1.id IN (SELECT * FROM source_ids),它不工作,因为它看起来应该,但什么?

+0

移动'及d1.id IN(SELECT * FROM source_ids) AND d2.id = 'ab3b516e-acd7-11e7-a0db-f23c91e2b423' WHERE d2.t IS NULL;''到WHERE'子句。 – lad2025

回答

2

当使用LEFT JOIN时,第一个表上的过滤器应该在WHERE子句中。 ON子句中的第二个上的过滤器。通常,第二张桌子上的过滤器出现错误。你的第一张桌子上有过滤器。

所以:

WITH source_ids AS (
    SELECT UNNEST(ARRAY['1e77b896-9e1b-11e7-a0db-f23c91e2b423'::uuid, '7dd37dd0-9e1a-11e7-a0db-f23c91e2b423'::uuid]) 
) 
INSERT INTO data_record (id, t) (
    SELECT DISTINCT 'ab3b516e-acd7-11e7-a0db-f23c91e2b423'::uuid, d1.t 
    FROM data_record d1 LEFT JOIN data_record 
      d2 
      ON d1.t = d2.t AND 
      d2.id = 'ab3b516e-acd7-11e7-a0db-f23c91e2b423'::uuid 
     WHERE d2.t IS NULL AND d1.id IN (SELECT * FROM source_ids); 

这似乎仍然过于复杂的我。我可能会建议:

WITH . . . 
SELECT DISTINCT 'ab3b516e-acd7-11e7-a0db-f23c91e2b423'::uuid, dr.t 
FROM (SELECT dr.*, 
      COUNT(*) FILTER (WHERE dr.id = 'ab3b516e-acd7-11e7-a0db-f23c91e2b423'::uuid) OVER (PARTITION BY t) as cnt 
     FROM data_record dr 
    ) dr 
WHERE cnt = 0; 

根据如何设置数据和索引,您的原始版本可能会更快。