简体   繁体   English

Oracle SQL-同一张表中基于彼此的多处条件

[英]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. 我只想选择在两组逻辑中都有(每个vnumcomp )行的行。

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. 因此,对于每个vnumcomp它都需要同时满足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.

相关问题 基于条件的Oracle SQL检索列都在同一张表中 - Oracle SQL Retrieving Columns based on conditions all in the same table Oracle SQL喜欢从其他表中选择的多个条件 - Oracle sql like multiple conditions with select from other table 根据有条件的其他表从表中选择 - Select from table based on other table with conditions Oracle SQL 将行转换为列并根据另一个表中的条件为它们提供另一个表中的值 - Oracle SQL Converting Rows into Columns and Giving them Values from another Table based on Conditions from another Table Oracle SQL查询表并根据结果从另一个表中删除 - Oracle SQL query a table and delete from an other based on the results 如何根据oracle / sql中的条件将数据插入表中 - How to insert data into a table based on conditions in oracle/sql 使用ORACLE / SQL根据单个表中的两个条件创建两个单独的列 - Create two separate columns based on two conditions from single table using ORACLE/SQL 使用其他表中的条件更新oracle中的表 - Updating a table in oracle with were conditions from other table Oracle:SQL根据同一表的另一行中的值更新同一表的行 - Oracle: Sql to update row of the same table based on value from another row of the same table Oracle - 根据不同的条件从不同的表返回相同的数据? - Oracle - Returning same data from different tables based on different conditions?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM