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

show all records in table 1 using many to many relations - postgresql

我正在尝试创建一个联系人报告,显示所有联系人和 select 在场的人。

存在存储在多对多table中。文档 ID 和出席者。

table如下:

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

提前感谢您提供任何线索。

我认为问题出在条件 presdoc=2 上,它强制 return 只有存在的记录。这就是你需要的。

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

你能像这样执行吗(如果你只需要检查是否存在)

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 

如果您只想检查您的文件是否已签发。然后另外你可以为你的布尔检查创建自定义聚合,逻辑类似于 "to become and stay true once it reached true":

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 即可。

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

SELECT     pename,coname,presdoc 
FROM       pe 
LEFT JOIN  co ON coid=peco 
LEFT JOIN  pres ON prespe=peid 
WHERE      peco = 1 AND presdoc=2 
UNION
SELECT     pename,coname,NULL AS present FROM pe 
LEFT JOIN  co ON coid=peco
WHERE      peco=1 AND peid NOT IN(SELECT prespe FROM pres WHERE presdoc=2)

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

谢谢!