我有一个表ledrow
,其中有4列。
我想只选择他们拥有的行(每个vnum
和comp
)两个逻辑集中的行。
英文解释
例如,在下面的所有数据中,解释预期输出中的行如下:
对于comp
99,我们得到了结果,因为所有vacc
个数字都属于任何一组逻辑:
vacc
是BETWEEN '1544' AND '1567'
或vacc
是BETWEEN '3000' AND '3999'
但是,例如comp
不输出77行,因为即使:
comp vtype vnum vacc
77 F 1369 3400
77 F 1369 3402
根据逻辑的第二部分,其余行不属于任何行:
comp vtype vnum vacc
77 F 1369 1510
77 F 1369 2620
77 F 1369 2620
77 F 1369 2620
77 F 1369 1650
这是因为要成为输出的一部分,我希望每个comp的所有行必须落在每个comp的逻辑的任一部分。
我尝试过以下代码,但无法获得预期的输出。
当前代码:
SELECT * FROM (
SELECT comp, vtype, vnum, vacc
FROM ledrow
WHERE
((comp = '55' AND vacc BETWEEN '1544' AND '1567') AND (comp = '55' AND (vacc = '3019' OR vacc = '5222')))
OR
((comp = '66' AND vacc BETWEEN '1544' AND '1567') AND (comp = '66' AND (vacc = '3013' OR (vacc BETWEEN '6910' AND '6973'))))
OR
((comp NOT IN ('55', '66') AND vacc BETWEEN '1544' AND '1567') AND (comp NOT IN ('55', '66') AND (vacc BETWEEN '3000' AND '3999')))) outputled
WHERE outputled.vtype = 'F'
预期产出:
comp vtype vnum vacc
99 F 1369 1564
99 F 1369 2610
99 F 1369 2610
99 F 1369 3601
99 F 1369 3600
完整表格(SELECT * FROM ledrow
):
ledrow
comp vtype vnum vacc
77 F 1369 1510
77 F 1369 2620
77 F 1369 2620
77 F 1369 2620
77 F 1369 3400
77 F 1369 3402
77 F 1369 1650
99 F 1369 1564
99 F 1369 2610
99 F 1369 2610
99 F 1369 3601
99 F 1369 3600
99 I 1369 2450
99 I 1369 2440
99 I 1369 2640
99 J 1369 5430
99 J 1369 2450
99 J 1369 5430
99 J 1369 2455
99 J 1369 5410
99 J 1369 2455
99 J 1369 5410
22 F 1369 2620
22 F 1369 3500
22 F 1369 2495
22 F 1369 1510
22 F 1369 2620
22 F 1369 2620
22 F 1369 2620
22 F 1369 2620
22 F 1369 2620
22 F 1369 2620
22 F 1369 2620
22 F 1369 2620
22 F 1369 2620
22 F 1369 3500
22 F 1369 3500
22 F 1369 3500
22 F 1369 3500
22 F 1369 3500
22 F 1369 3500
22 F 1369 3500
22 F 1369 3500
22 F 1369 3500
22 F 1369 3500
22 F 1369 3500
22 F 1369 2495
22 F 1369 3500
22 F 1369 2495
22 F 1369 3500
22 F 1369 2495
22 F 1369 3500
22 F 1369 2495
22 F 1369 3500
22 F 1369 2495
22 F 1369 3500
22 F 1369 2495
22 F 1369 3500
22 F 1369 2495
22 F 1369 3500
22 F 1369 2495
22 F 1369 3500
22 F 1369 2495
22 I 1369 2450
22 I 1369 2440
22 I 1369 2640
22 J 1369 5520
22 J 1369 5520
22 J 1369 2455
22 J 1369 2450
修改
因此,对于每个vnum
和comp
,它需要满足WHERE子句中的两个条件。
因此comp
99
必须满足这两个条件:
((comp NOT IN ('55', '66') AND vacc BETWEEN '1544' AND '1567') AND (comp NOT IN ('55', '66') AND (vacc BETWEEN '3000' AND '3999'))))
答案 0 :(得分:3)
如果我理解你想要做什么,那么这应该有效:
WHERE comp = '55' AND (vacc between '1544' and '1567' or vacc in('3019','5222')) OR
(comp = '66' AND (vacc between '1544' and '1567' or vacc between '6910' AND '6973' or vacc = '3013')) OR
(comp not IN('55','66') and (vacc BETWEEN '1544' AND '1567' or vacc BETWEEN '3000' AND '3999'))
您指定了每个第一个条件两次,这是不必要的,因为它们对于下两个条件都是正确的。
(comp not IN('55','66') AND Cond1) AND/OR (comp not IN('55','66') AND Cond2)
等于:
comp not IN('55','66') AND (Cond1 AND/OR Cond2)
编辑你可以尝试这样的事情:
SELECT tt.* FROM (
SELECT t.comp FROM (
SELECT comp,
CASE WHEN comp = '55' AND vacc BETWEEN '1544' AND '1567' THEN 1
WHEN comp = '55' AND vacc in('3019','5222') THEN 2
WHEN comp = '66' AND vacc BETWEEN '1544' AND '1567' THEN 3
WHEN comp = '66' AND (vacc = '3013' OR (vacc BETWEEN '6910' AND '6973')) THEN 4
WHEN comp NOT IN ('55', '66') AND vacc BETWEEN '1544' AND '1567' THEN 5
WHEN comp NOT IN ('55', '66') AND (vacc BETWEEN '3000' AND '3999') THEN 6
ELSE 7
END as ind_col
FROM ledrow
WHERE vtype = 'F') t
GROUP BY t.comp
HAVING (MAX(t.ind_col) = 2 and min(t.ind_col) = 1) OR
(MAX(t.ind_col) = 4 and min(t.ind_col) = 3) OR
(MAX(t.ind_col) = 6 and min(t.ind_col) = 5)) s
INNER JOIN ledrow tt
ON(s.comp = tt.comp)
WHERE tt.vtype = 'F'
这基本上会给出每一行的指示,第一个条件是1,2
,对应于满足条件的部分,第二个是3,4
,第三个是5,6
。然后,检查每个组只有1 + 2或3 + 4或5 + 6与HAVING
子句MAX()
和MIN()
,这将确保此comp
满足两个条件。
此解决方案仅适用于满足这两个条件的行,而不仅仅适用于其中一个行。如果只有其中一个就足够了,那就将having子句更改为:
HAVING (MAX(t.ind_col) = 2 and min(t.ind_col) = 1) OR
(MAX(t.ind_col) = 4 and min(t.ind_col) = 3) OR
(MAX(t.ind_col) = 6 and min(t.ind_col) = 5) OR
(MAX(t.ind_col) = min(t.ind_col) and min(t.ind_col) IN(1,2,3,4,5,6)
答案 1 :(得分:2)
可能我已经理解了你想要的东西:)
我们为每个comp(group by comp)创建每个特殊条件,就像一个字节(1,2,4,8)中的位,然后添加它们。比我们只选择我们想要的组合。 (1 + 2 = 3,1 + 4 = 5,1 + 8 = 9)
SELECT *
FROM ledrow
WHERE vtype = 'F'
AND comp IN
(SELECT comp
FROM ( SELECT comp,
MAX (CASE WHEN (vacc BETWEEN '1544' AND '1567') THEN 1 ELSE 0 END)
+ MAX (CASE WHEN (comp = '55' AND vacc IN ('3019', '5222')) THEN 2 ELSE 0 END)
+ MAX (CASE WHEN (comp = '66' AND (vacc = '3013' OR vacc BETWEEN '6910' AND '6973')) THEN 4 ELSE 0 END)
+ MAX (CASE WHEN (comp NOT IN ('55', '66') AND vacc BETWEEN '3000' AND '3999') THEN 8 ELSE 0 END)
x
FROM ledrow
WHERE vtype = 'F'
GROUP BY comp)
WHERE bitand(x,3) = 3 OR bitand(x,5) = 5 OR bitand(x,9) = 9)
使用分析函数MAX() OVER ()的另一个修改,但逻辑相同
SELECT comp, vtype, vnum, vacc
FROM (SELECT x.*,
MAX (CASE WHEN (vacc BETWEEN '1544' AND '1567') THEN 1 ELSE 0 END) OVER (PARTITION BY comp) c1,
MAX (CASE WHEN (comp = '55' AND vacc IN ('3019', '5222')) THEN 1 ELSE 0 END) OVER (PARTITION BY comp) c2,
MAX (CASE WHEN (comp = '66' AND (vacc = '3013' OR vacc BETWEEN '6910' AND '6973')) THEN 1 ELSE 0 END) OVER (PARTITION BY comp) c4,
MAX (CASE WHEN (comp NOT IN ('55', '66') AND vacc BETWEEN '3000' AND '3999') THEN 1 ELSE 0 END) OVER (PARTITION BY comp) c8
FROM testtest2 x
WHERE vtype = 'F')
WHERE (c1 = 1 AND c2 = 1)
OR (c1 = 1 AND c4 = 1)
OR (c1 = 1 AND c8 = 1)