SQL查询可获取子表1和子表2中没有特定值的父级

时间:2019-01-09 13:53:36

标签: postgresql

我有一个父表,其中有几个子表。亲子关系是一对二的。我必须让父母让他们的孩子没有某些价值观。子表中的值是不同的,因此,如果一个表具有该值,则并不意味着它在其他表中。

我只尝试了普通的INNER JOIN和WHERE NOT IN(代码),但是它得到了所有记录。 由于UNION,以下代码无法正常工作。对于UNION,在子表2中没有代码的父母和在子表2中没有代码的父母。

SELECT DISTINCT PAYSLIP.id, PAYSLIP.year, PAYSLIP.month 
FROM (
    SELECT p.id, p.year, p.month
    FROM history_payslip_data p 
    INNER JOIN history_payslip_data_hours pu ON p.id = pu.payslip_id 
    INNER JOIN history_payslip zg ON p.payslip_id = zg.id 
    WHERE NOT EXISTS (
         SELECT 1 
         FROM history_payslip_data_hours pu2
         WHERE p.id = pu2.payslip_id
         AND pu2.code IN ('code1', 'code2', 'code3')
    )
    AND (p.employee_id IN (2) AND p.payslip_type = 'PL' AND zg.locked = TRUE)   
    UNION 
    SELECT p.id, p.year, p.month
    FROM history_payslip_data p 
    INNER JOIN history_payslip_data_other pd ON p.id = pd.payslip_id 
    INNER JOIN history_payslip zg ON p.payslip_id = zg.id 
    WHERE NOT EXISTS (
         SELECT 1 
         FROM history_payslip_data_other pd2
         WHERE p.id = pd2.payslip_id
         AND pd2.code IN ('code1', 'code2', 'code3')
    )
    AND (p.employee_id IN (2) AND p.payslip_type = 'PL' AND zg.locked = TRUE)

) AS PAYSLIP
ORDER BY PAYSLIP.year DESC, PAYSLIP.month DESC; 

我想让没有任何子表中的代码的父母。

1 个答案:

答案 0 :(得分:0)

您可以通过以下方式来实现此目的:针对您要禁止显示父结果的每种子表类型,LEFT JOIN针对CTE(我将history_payslip.id更改为payslip_id以进行联接更简单):

WITH hours AS (
SELECT hpd.payslip_id, hpd.employee_id, hpd.year, hpd.month
  FROM history_payslip_data hpd
  --JOIN history_payslip hp USING (payslip_id)
  JOIN history_payslip_data_hours h USING (payslip_id)
 WHERE h.code in ('code1', 'code2', 'code3')
), other AS (
SELECT hpd.payslip_id, hpd.employee_id, hpd.year, hpd.month
  FROM history_payslip_data hpd
  --JOIN history_payslip hp USING (payslip_id)
  JOIN history_payslip_data_other o USING (payslip_id)
 WHERE o.code in ('code1', 'code2', 'code3')
)

SELECT hp.payslip_id as pid, hpd.employee_id as eid, hpd.year, hpd.month
  FROM history_payslip_data hpd
  JOIN history_payslip hp USING (payslip_id)
  LEFT JOIN hours h USING (payslip_id, employee_id)
  LEFT JOIN other o USING (payslip_id, employee_id)
 WHERE hpd.payslip_type = 'PL'
   AND hp.locked IS true
   AND h.payslip_id IS NULL
   AND o.payslip_id IS NULL

这是我正在测试的方式,上面的查询另存为new-query.sql

main.sql:

CREATE SCHEMA so54111738;
SET search_path=so54111738;

\i ./tables.ddl
\i ./setup.sql
--\i ./query.sql
\i ./new-query.sql

DROP SCHEMA so54111738 CASCADE;

tables.ddl:

CREATE TABLE history_payslip (
  payslip_id int,
  locked boolean
);

CREATE TABLE history_payslip_data (
  id serial,
  employee_id int,
  payslip_id int,
  payslip_type text,
  year int,
  month int
);

CREATE TABLE history_payslip_data_hours (
  payslip_id int,
  code text
);

CREATE TABLE history_payslip_data_other (
  payslip_id int,
  code text
);

setup.sql:

/* these two groups of inserts represent a payslip plus an hours row that means it should be excluded */
/* payslip 1 for employee 2; hours entry with code 4 */
INSERT INTO history_payslip (payslip_id, locked) VALUES (1, true);
INSERT INTO history_payslip_data (payslip_id, payslip_type, employee_id, year, month) VALUES (1, 'PL', 2, 2018, 12);
INSERT INTO history_payslip_data_hours (payslip_id, code) VALUES (1, 'code4');

/* payslip 1 for employee 2; hours entry with code 3 */
INSERT INTO history_payslip (payslip_id, locked) VALUES (1, true);
INSERT INTO history_payslip_data (payslip_id, payslip_type, employee_id, year, month) VALUES (1, '??', 2, 2018, 12);
INSERT INTO history_payslip_data_hours (payslip_id, code) VALUES (1, 'code3');


/* these two groups of inserts represent a payslip plus an other row that means it should be excluded */
/* payslip 2 for employee 3; other entry with code 4 */
INSERT INTO history_payslip (payslip_id, locked) VALUES (2, true);
INSERT INTO history_payslip_data (payslip_id, payslip_type, employee_id, year, month) VALUES (2, 'PL', 3, 2018, 11);
INSERT INTO history_payslip_data_other (payslip_id, code) VALUES (2, 'code4');

/* payslip 2 for employee 3; other entry with code 3 */
INSERT INTO history_payslip (payslip_id, locked) VALUES (2, true);
INSERT INTO history_payslip_data (payslip_id, payslip_type, employee_id, year, month) VALUES (2, '??', 3, 2018, 11);
INSERT INTO history_payslip_data_other (payslip_id, code) VALUES (2, 'code3');


/* this group of inserts represents a payslip that should be returned because it has no matching hours or other entries */
/* payslip 5 for employee 5; hours entry with code 4 */
INSERT INTO history_payslip (payslip_id, locked) VALUES (5, true);
INSERT INTO history_payslip_data (payslip_id, payslip_type, employee_id, year, month) VALUES (5, 'PL', 5, 2018, 10);
INSERT INTO history_payslip_data_hours (payslip_id, code) VALUES (5, 'code4');