使用多对多关系显示表1中的所有记录 - postgresql

时间:2016-03-11 09:53:38

标签: sql postgresql postgresql-9.1

我正在尝试创建一个联系人报告,显示所有联系人并选择那些在场的人。

存在存储在多对多表中。文件ID和谁在场。

表格如下:

CREATE TABLE pe
    (peid int4, peco int4, pename varchar(30));
INSERT INTO pe
    (peid, peco, pename)
VALUES
    (1, 1,'Carl'),
    (2, 1,'John'),
    (3, 1,'Eric'),
    (4, 2,'Donald')
;

CREATE TABLE co
    (coid int, coname varchar(30));
INSERT INTO co
    (coid, coname)
VALUES
    (1,'Volvo'),
    (2,'BMW'),
    (3,'Microsoft'),
    (4,'Apple')
;

There is a also a doc table that is not needed for this query

CREATE TABLE pres 
    (presid int4, presdoc int4, prespe int4);
INSERT INTO pres
    (presid, presdoc, prespe)
VALUES
    (1,1,1),
    (2,2,2),
    (3,2,3),
    (4,3,1)
;   

不起作用的查询(无论连接类型如何):

SELECT     pename,coname,presdoc AS present 
FROM       pe 
LEFT JOIN  co ON coid=peco
LEFT JOIN  pres ON prespe=peid
WHERE      peco = 1 AND presdoc=2

此查询的输出是

John    Volvo  present
Eric    Volvo  present

所需的输出是

Carl    Volvo
John    Volvo  present
Eric    Volvo  present

SQLFiddle:

http://sqlfiddle.com/#!15/77b09/21

提前感谢任何线索。

4 个答案:

答案 0 :(得分:1)

我认为问题在于条件presdoc=2迫使只返回存在的记录。这就是你需要的。

SQLFiddle Demo

SELECT pename,
       coname,
       CASE
           WHEN presdoc=2 THEN 'Present'
           ELSE NULL
       END AS Present
FROM pe
LEFT JOIN co ON coid=peco
LEFT JOIN pres ON prespe=peid
WHERE peco = 1
GROUP BY pename,
         coname,
         present

答案 1 :(得分:1)

你可以这样做(如果你只需要检查是否存在)

SELECT     pename,coname,presdoc = 2 AS present 
FROM       pe 
LEFT JOIN  co ON coid=peco
LEFT JOIN  pres ON prespe=peid
WHERE      peco = 1

甚至更好

SELECT DISTINCT     pename,coname,presdoc = 2 AS present 
FROM       pe 
LEFT JOIN  co ON coid=peco
LEFT JOIN  pres ON prespe=peid
WHERE      peco = 1 

答案 2 :(得分:0)

如果您想检查一下您的文件是否已经发出。然后你可以为你的布尔检查创建自定义聚合,逻辑就像“一旦达到真实就变成并保持真实”:

create or replace function max_boolean(agg_state boolean)
returns boolean
immutable
strict
language plpgsql
as $$
begin
  return agg_state;
end;
$$;



create or replace function max_boolean_aggregate(agg_state boolean, el boolean)
returns boolean
immutable
language plpgsql
as $$
begin 
  if (agg_state = true) then
    return true;
  else
      if (el is null) then 
        return false;
      else 
        return el;
      end if; 
  else 
    return el;
  end if;
end;
$$;



create aggregate max_boolean_aggregate (boolean)
(
    sfunc = max_boolean_aggregate,
    stype = boolean,
    finalfunc = max_boolean
);

然后您的查询可以重写如下:

SELECT DISTINCT     pename,coname,  max_boolean_aggregate(presdoc = 2) AS present 
FROM       pe 
left   JOIN  co ON coid=peco
left   JOIN  pres ON prespe=peid
WHERE      peco = 1 
group by pename, coname 

它会显示您的人是否收到了该文件。

甚至可以支持多项检查:-)

只需将max_boolean_aggregate()内的条件更改为(2,3)中的presdoc就可以了。

答案 3 :(得分:0)

基本上@Ilya Dyoshin有解决方案。我只是把他的小评论写进了答案。首先找到现有的,然后UNION不存在。使用NOT IN比不存在恕我直言更简单。

photoGallery

SQLFiddle:http://sqlfiddle.com/#!15/fb571/117

谢谢!