【问题标题】:Retrieving based on specific condition根据特定条件检索
【发布时间】:2021-02-10 22:55:44
【问题描述】:

我对几个很难破解的表有一些复杂的要求。

有 2 张桌子。表A和表B

TableA 的结构类似于

-------------------------------------
ID      COL1        COL2        CAT
-------------------------------------
1       RecAA       RecAB       3
2       RecBA       RecBB       3
3       RecCA       RecCB       2
4       RecDA       RecDB       2
5       RecEA       RecEB       1
-------------------------------------

TableB 的结构类似于

-----------------
COL3        TYPE
-----------------
RecAA       10
RecAA       11
RecAA       12
RecAB       10
RecAB       11
RecAB       12
RecAB       13
RecAB       14
RecBA       10
RecBA       11
RecBA       14
RecBA       15
RecBB       10
-----------------

要求

  1. 表 A 中的记录的 CAT = 3。
  2. TableA 的 COL1 或 COL2 应在 TableB 的 COL3 中可用。
  3. COL3 绝对应该在 10、11、12 中有 TYPE,并且应该只有那个 TYPE。

按照上述要求

  1. 在 TableA 中可用的记录中,ID 为 1 和 2 的记录在 TableA 中的 CAT = 3
  2. 两条记录至少只有 TableB 的 COL3 中的值。 (表A中ID为1的记录在表B中同时具有COL1和COL2,表A中ID为2的记录在表B中具有COL1)
  3. RecAA 记录的类型为 10、11、12,并且只有 10、11、12。所以 RecAB 是否有 10、11、12 并不重要。但是 RecBA 和 RecBB 都没有 10,11,12 类型。

因此结果应该是

-------------------------------------
ID      COL1        COL2        CAT
-------------------------------------
1       RecAA       RecAB       3
-------------------------------------

我尝试了什么

WITH TEMP AS (SELECT COL3 FROM TableB GROUP BY COL3 HAVING SUM(CASE WHEN TYPE IN ('10','11','12') THEN 1 ELSE 0 END) = 0)
SELECT S.ID, S.COL1, S.COL2, S.CAT FROM TableA S
INNER JOIN TEMP T ON S.COL1 = T.COL3
WHERE S.CAT = 3;

有人可以帮助实现这一目标吗?

【问题讨论】:

    标签: oracle


    【解决方案1】:

    我想你快到了,只是你在 CTE 中的行选择似乎有问题,我认为你需要一个 OR:

    WITH TEMP AS (
      SELECT COL3 
      FROM TableB 
      GROUP BY COL3 
      HAVING SUM(POWER(2, TYPE - 10)) = 7 AND COUNT(*) = 3
    )
    
    SELECT
      S.ID, S.COL1, S.COL2, S.CAT 
    FROM 
      TableA S
      INNER JOIN TEMP T ON S.COL1 = T.COL3 OR S.COL2 = T.COL3
    WHERE 
      S.CAT = 3;
    

    我从您的每个 TYPE 中减去 10,将您的 10,11,12 变成 0,1,2,然后使用 POWER 将它们变成 1、2 和 4,它们的总和为 7 -(换句话说你的 10、11、12 变成了 2^(10-10)2^(11-10)2^(12-10),它们分别是 1、2 和 4.. 然后它们的总和必须为 7)。

    我还要求计数为 3;用三个 2 的幂数达到 7 的唯一方法是使用 1+2+4,这可以保证最初存在 10、11、12。如果有任何遗漏、多余或重复,则不会是 3 个数字的总和为 7

    我认为 RecAB 被排除在外,因为即使它有 10,11,12 它也有 13,14 导致它被排除在外..

    您似乎还说 COL3 应该出现在表 A 的 COL1 或 COL2 中

    【讨论】:

    • 你说得对,Caius。 !!这似乎是正确的方法。但是表B中提到的类型只是一个例子,10、11、12的实际值是80000、80001、80002。2的幂是指数! :( 还有其他解决方案吗?
    • 好的。我正在尝试没有权力。只会比较 TYPE 的总和。
    • 我使用“负 10”将 10/11/12 降低到 0/1/2。看起来你应该减去 80000 ?
    • 有很多方法可以使用这种技巧,使用 10 的幂而不是 2 的幂可能对您更有意义,例如SUM(POWER(10, TYPE-80000)) = 111 并以 10 的幂.. 或 CASE TYPE WHEN 80000 THEN 100 WHEN 80001 THEN 10 WHEN 80002 THEN 1 ELSE 1000 END) = 111 - 后一种技巧非常适合非顺序或字母等的东西。基本上我们希望以某种东西的全部力量工作(如 2 或 10)并确保总和只能以一种方式相加 - 使用这些技术只有一种方式可以达到 111(即 80000/80001/80002 变为 111.. 其他任何方式都不会)
    • 非常感谢凯厄斯!很好的答案。
    【解决方案2】:

    您可以使用 listagg 解析版本将 TYPE 列转换为 type_in_list 列,如下所示:

    With temp_TableB (COL3, type_in_list) as (
      SELECT distinct COL3, listagg(TYPE, ',') within group (order by TYPE)over(partition by COL3) 
      FROM TableB
    )
    select tA.*
    --, tb.*
    from tableA tA
    INNER JOIN temp_TableB tB on (tA.COL1 = tB.COL3 or tA.COL2 = tB.COL3)
    Where tA.CAT = 3
    AND tB.TYPE_IN_LIST = '10,11,12'
    ;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-30
      • 2014-06-19
      • 2022-11-01
      • 2012-06-10
      • 2020-12-30
      • 2014-01-24
      • 2018-08-24
      相关资源
      最近更新 更多