在 SQL Oracle 的 B 列中搜索 A 列的每个值

Posted

技术标签:

【中文标题】在 SQL Oracle 的 B 列中搜索 A 列的每个值【英文标题】:Search each value of Column A in Column B in SQL Oracle 【发布时间】:2019-04-16 14:14:55 【问题描述】:

假设我有这种类型的数据集:

row     Num_A   Num_B    Num_C    Reg_1    Reg_2
------  -----   -----    -----    -----    -----
   1    9400    9500     9700     AAA      CCC
   2    9700    9400     9500     BBB      DDD
   3    9500    9400     9200     EEE      AAA
   4    9100    9300     9900     AAA      DDD

考虑以下条件:

在第 1 行中,Num_B"95000" 出现在 Num_A(第 3 行)中,对应的 Num_A(第 1 行)"94000" 等于它的Num_B(第 3 行)(即案例`“94000”)

因此,新列 Comm_1 将具有 Num_ANum_B 的组合作为其值。 Comm_2 也是如此

对于Comm_3,条件与Comm_1Comm_2相同,还有一个附加条件是第1行的Reg_1(或Reg_2'AAA'(或'CCC')相等到第 3 行的 Reg_1Reg_2(就是这种情况)。

我想构造一个查询,结果如下所示:

    row     Num_A   Num_B    Num_C    Reg_1    Reg_2   Comm_1     Comm_2     Comm_3
    ------  -----   -----    -----    -----    -----   -----     -----     -----
       1    9400    9500     9700     AAA      CCC     94009500  94009700  94009500
       2    9700    9400     9500     BBB      DDD     97009400  97009500  NULL
       3    9500    9400     9200     EEE      AAA     95009400  NULL      95009400
       4    9100    9300     9900     AAA      DDD     NULL      NULL      NULL

我尝试了以下基本语法,但它不起作用:

SELECT 
       IF(Num_B in (select distinct Num_A from mydata) , concat(Num_A,Num_B), Null) as Comm_1,
       IF(Num_C in (select distinct Num_A from mydata) , concat(Num_A,Num_C), Null) as Comm_2
FROM mydata

所以请提供任何提示,并让我阅读pl/sql 中的正确观点或我需要学习的任何程序。

【问题讨论】:

您输入和输出中的数字不同,我不明白您要应用的逻辑。 (我真的不确定“通讯员 Num_A “94000”是否等同于他的 Num_A” - 那应该是“......他的 Num_B”吗?)你能编辑你的问题澄清一下吗? 现有查询的输出是什么? @SamChats,第 4 行正在获取 NULL for Comm_3,因为 93009900Num_BNum_C)不在 Num_A 列表中跨度> @SamChats,这是第 1 行的示例,其余行相同 我不确定这是否有帮助,抱歉;最好在问题中充分解释。不过,我看不到任何与答案相矛盾的东西;如果这些是错误的,那么你需要解释原因。 【参考方案1】:

你可以通过外部自连接获得(我认为)你想要的东西:

-- CTE for sample data, including row_num to maintain display order
with mydata (row_num, Num_A, Num_B, Num_C, Reg_1, Reg_2) as (
  select 1, 94000, 95000, 97000, 'AAA', 'CCC' from dual
  union all select 2, 97000, 94000, 95000, 'BBB', 'DDD' from dual
  union all select 3, 95000, 94000, 92000, 'EEE', 'AAA' from dual
  union all select 4, 91000, 93000, 99000, 'AAA', 'DDD' from dual
)
-- actual query
select m.*,
  case when m1.num_a is not null then m.num_a || m1.num_a end as comm_1,
  case when m2.num_a is not null then m.num_a || m2.num_a end as comm_2,
  case when m3.num_a is not null then m.num_a || m3.num_a end as comm_3
from mydata m
left join mydata m1 on m1.num_a = m.num_b
left join mydata m2 on m2.num_a = m.num_c
left join mydata m3 on m3.num_a = m.num_b and (m3.reg_1 = m.reg_2 or m3.reg_2 = m.reg_1)
order by m.row_num;

   ROW_NUM      NUM_A      NUM_B      NUM_C REG REG COMM_1     COMM_2     COMM_3    
---------- ---------- ---------- ---------- --- --- ---------- ---------- ----------
         1      94000      95000      97000 AAA CCC 9400095000 9400097000 9400095000
         2      97000      94000      95000 BBB DDD 9700094000 9700095000           
         3      95000      94000      92000 EEE AAA 9500094000            9500094000
         4      91000      93000      99000 AAA DDD                                 

(我留在row_num 只是为了保持显示顺序相同,否则不会使用它;我假设这实际上不是您表格中的一列。)

comm_1 值基于与另一行的左连接,该行的num_a 与该行的num_b 匹配。

comm_2 值基于与另一行的左连接,该行的num_a 与该行的num_c 匹配。

comm_3 值与comm_1 相同,但还必须将其reg_1 与另一行的reg_2 匹配,反之亦然。 但是,这会将第 3 行的值计算为 9500094000,而不是问题中显示的 94009500 - 虽然不清楚哪个是正确的。

如果任何外连接有多个匹配项,这也会得到重复的行;您的示例数据并非如此,但需要注意一些事情。如果发生这种情况,我不知道你会如何处理。


您也可以在列表达式中使用单个外连接和更多逻辑/聚合来实现:

select m.row_num, m.num_a, m.num_b, m.num_c, m.reg_1, m.reg_2,
  max(case when m1.num_a = m.num_b then m.num_a || m1.num_a end) as comm_1,
  max(case when m1.num_a = m.num_c then m.num_a || m1.num_a end) as comm_2,
  max(case when m1.num_a = m.num_b and (m1.reg_1 = m.reg_2 or m1.reg_2 = m.reg_1)
    then m.num_a || m1.num_a end) as comm_3
from mydata m
left join mydata m1 on (m1.num_a = m.num_b) or (m1.num_a = m.num_c)
group by m.row_num, m.num_a, m.num_b, m.num_c, m.reg_1, m.reg_2
order by m.row_num;

   ROW_NUM      NUM_A      NUM_B      NUM_C REG REG COMM_1     COMM_2     COMM_3    
---------- ---------- ---------- ---------- --- --- ---------- ---------- ----------
         1      94000      95000      97000 AAA CCC 9400095000 9400097000 9400095000
         2      97000      94000      95000 BBB DDD 9700094000 9700095000           
         3      95000      94000      92000 EEE AAA 9500094000            9500094000
         4      91000      93000      99000 AAA DDD                                 

【讨论】:

好的,非常感谢,这适用于我的示例,我将在孔数据集上运行它,并使用其他条件(Num_A 已分组和一些其他问题),然后我将返回最终数据集完成后,再次感谢您:) 好的,谢谢,我用其他一些条件在整个数据库上运行它,但条件或 reg 不在连接语句中,但在查询的情况下,它工作得很好(否则它也需要很多时间),再次感谢:) 但只是一个问题,当我们需要使用循环和 pl/sql 时?【参考方案2】:

如果我正确理解逻辑,您可以使用这些子查询:

select row_, Num_A, Num_B, Num_C, Reg_1, Reg_2, 
       (select min(m.num_a||' '||m.num_b) from mydata where num_a = m.num_b ) comm_1,
       (select min(m.num_a||' '||m.num_c) from mydata where num_a = m.num_c ) comm_2,
       (select min(m.num_a||' '||m.num_b) from mydata 
         where num_a = m.num_b and (reg_2 = m.reg_1 or reg_1 = m.reg_2)) comm_3
  from mydata m

demo

我使用min 以防有很多匹配的行。

【讨论】:

好的,非常感谢,这适用于我的示例,我将在孔数据集上运行它,并使用其他条件(Num_A 已分组和其他一些问题),然后我将返回最终数据集完成后,再次感谢您:) 好的,谢谢,但我选择了第一个解决方案,因为它要快得多,谢谢 :)

以上是关于在 SQL Oracle 的 B 列中搜索 A 列的每个值的主要内容,如果未能解决你的问题,请参考以下文章

oracle 两表中两列模糊查询,具体例子如下:

Oracle同一列中存放数字或字母时的排序

Oracle - 在所有表中搜索所有列中的数据

Excel搜索Word是否在列A中的某个位置以及列B中

使用同一列中的值更新表中的唯一列

SQL WHERE 匹配任何列中的任何值