我有一个父表,其中有几个子表。亲子关系是一对二的。我必须让父母让他们的孩子没有某些价值观。子表中的值是不同的,因此,如果一个表具有该值,则并不意味着它在其他表中。
我只尝试了普通的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;
我想让没有任何子表中的代码的父母。
答案 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');