[英]Oracle SQL - Multiplewhere conditions based on each other from the same table
I have a single table ledrow
Which has 4 columns. 我有一个表
ledrow
其中有4列。
I want to only select rows where they have (per vnum
and comp
) rows that are in both sets of logic. 我只想选择在两组逻辑中都有(每个
vnum
和comp
)行的行。
English Explanation 英文说明
So for example out of all the data below, explaining the rows in the expected output is as follows: 因此,例如,在下面的所有数据中,解释预期输出中的行如下:
For comp
99 we have results as all of the vacc
numbers fall into either of the sets of logic: 对于
comp
99,我们得到的结果是所有vacc
编号都属于以下两种逻辑之一:
The vacc
is either BETWEEN '1544' AND '1567'
OR the vacc
is BETWEEN '3000' AND '3999'
vacc
是在BETWEEN '1544' AND '1567'
在vacc
是在BETWEEN '3000' AND '3999'
However for example comp
77 rows aren't output because even though: 但是,例如
comp
77行不会输出,因为即使:
comp vtype vnum vacc
77 F 1369 3400
77 F 1369 3402
Comes under the second part of the logic the rest of the rows don't fall under any: 属于逻辑的第二部分,其余行不属于任何逻辑:
comp vtype vnum vacc
77 F 1369 1510
77 F 1369 2620
77 F 1369 2620
77 F 1369 2620
77 F 1369 1650
This is because to be part of the output I want all rows per comp MUST fall in either parts of the logic per comp. 这是因为要成为输出的一部分,我希望每个comp的所有行都必须属于每个comp的逻辑的任一部分。
I have tried the following code but cannot get my expected output. 我尝试了以下代码,但无法获得预期的输出。
Current Code: 当前代码:
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'
Expected Output: 预期产量:
comp vtype vnum vacc
99 F 1369 1564
99 F 1369 2610
99 F 1369 2610
99 F 1369 3601
99 F 1369 3600
Full Table ( SELECT * FROM ledrow
): 全表(
SELECT * FROM ledrow
):
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
Edit 编辑
So for each vnum
and comp
it needs to satisfy both of the two conditions in the WHERE clause. 因此,对于每个
vnum
和comp
它都需要同时满足WHERE子句中的两个条件。
So for comp
99
which has to satisfy both the conditions: 因此对于必须满足两个条件的
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'))))
If I understood what you were trying to do, then this should work : 如果我了解您要执行的操作,则此方法应该有效:
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'))
You specified each of the first conditions twice, which is not necessary as they are correct to both of the next conditions. 您指定了每个第一个条件两次,这是不必要的,因为它们对于两个下一个条件都是正确的。
(comp not IN('55','66') AND Cond1) AND/OR (comp not IN('55','66') AND Cond2)
Equals to: 等于:
comp not IN('55','66') AND (Cond1 AND/OR Cond2)
EDIT: You can try something like this: 编辑:您可以尝试这样的事情:
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'
This will basically give an indication to each row, first condition is 1,2
corresponding to the part of this condition the satisfied , second one is 3,4
and third is 5,6
. 这基本上将给每行一个指示,第一个条件是
1,2
对应于该条件所满足的部分,第二个条件是3,4
,第三个条件是5,6
。 Then you check that each group only has 1+2 or 3+4 or 5+6 with the HAVING
clause with MAX()
and MIN()
which will assure that this comp
satisfy both conditions. 然后,使用
HAVING
子句的MAX()
和MIN()
来检查每个组是否只有1 + 2或3 + 4或5 + 6,这将确保此comp
满足两个条件。
This solution works only for rows that satisfy both conditions, not only one of them. 此解决方案仅适用于同时满足两个条件的行,而不是其中一个条件。 If only one of them is enough, that change the having clause to this:
如果仅其中之一就足够了,那就将hading子句更改为:
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)
May be I have understood what you want :) 可能是我已经了解您想要的东西了:)
We make every special conditions per comp (group by comp) like a bit in a byte (1,2,4,8) and then add them. 我们使每个comp(按comp分组)的每个特殊条件都像一个字节(1,2,4,8)一样,然后将它们相加。 Than we choose only the combination what we want.
比我们只选择我们想要的组合。 (1+2=3, 1+4=5, 1+8=9)
(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)
Another modification with analytic function MAX() OVER () , but the same logic 带有分析函数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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.