【问题标题】:select query to fetch rows corresponding to all values in a column选择查询以获取对应于列中所有值的行
【发布时间】:2016-02-05 21:59:30
【问题描述】:

考虑这个示例表“Table1”。

Col1   Col2
 A      1
 B      1
 A      4
 A      5
 A      3
 A      2
 D      1
 B      2
 C      3
 B      4

我正在尝试从 Col1 中获取与所有值相对应的值(在本例中为 1、2、3、4、5)。此处查询的结果应返回“A”,因为其他查询的 Col2 中没有一个具有所有值 1,2,3,4,5。

请注意,Col2 中的值由查询中的其他参数决定,它们总是会返回一些数值。在这些值中,查询需要从 Col1 中获取对应于 Col2 中所有值的值。 Col2 中的值例如可以是 11,12,1,2,3,4(表示不一定按顺序排列)。

我尝试了以下选择查询:

select distinct Col1 from Table1 where Col1 in (1,2,3,4,5);

select distinct Col1 from Table1 where Col1 exists (select distinct Col2 from Table1);

及其不同的变体。但问题是我需要为 Col2 应用“和”而不是“或”。

like 从 Col1 返回一个值,其中 Col2“包含”1 到 5 之间的所有值。

感谢任何建议。

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    您可以使用解析 ROW_NUMBER() 函数。

    SQL FIddle 进行设置和工作演示。

    SELECT col1
    FROM
      (SELECT col1,
        col2,
        row_number() OVER(PARTITION BY col1 ORDER BY col2) rn
      FROM your_table
      WHERE col2 IN (1,2,3,4,5)
      )
    WHERE rn =5;
    

    更新应 OP 的要求,对查询的工作原理进行一些说明。

    内部子查询为您提供以下结果集:

    SQL> SELECT col1,
      2    col2,
      3    row_number() OVER(PARTITION BY col1 ORDER BY col2) rn
      4  FROM t
      5  WHERE col2 IN (1,2,3,4,5);
    
    C       COL2         RN
    - ---------- ----------
    A          1          1
    A          2          2
    A          3          3
    A          4          4
    A          5          5
    B          1          1
    B          2          2
    B          4          3
    C          3          1
    D          1          1
    
    10 rows selected.
    

    PARTITION BY 子句将对 col1 的每组集合进行分组,ORDER BY 将对 col1 的每组集合中的 col2 进行排序。因此,子查询以有序的方式为您提供每一行的 row_number。现在您知道您只需要那些 row_number 至少为 5 的行。因此,在外部查询中,您需要做的只是WHERE rn =5 来过滤行。

    【讨论】:

    • 这行得通。我将尝试检查所有情况。另外,您介意详细说明查询吗?我之前没有使用过 OVER 或 PARTITION 查询参数。
    • @Hemang 是解析函数。 PARTITION BY 子句将对 col1 的每组集合进行分组,ORDER BY 将对 col1 的每组集合中的 col2 进行排序。因此,子查询以有序的方式为您提供每一行的 row_number。请参阅更新说明。
    • 好的,很好。知道了。是的,我只是用我的扩展查询(包括其他参数)检查它,所以如果有任何查询/错误,我可以在接受之前咨询你。 Def现在将接受。感谢您的解决方案和解释。
    【解决方案2】:

    你可以使用listagg函数,比如

    SELECT Col1
    FROM
    (select Col1,listagg(Col2,',')  within group (order by Col2) Col2List  from Table1
    group by Col1)
    WHERE Col2List = '1,2,3,4,5'
    

    【讨论】:

    • 谢谢。首先,我认为 Col2List 将在 'from Table1' 之前出现,否则会出现错误。还有一个问题,如果我有额外的“哪里”条件,他们会去哪里?我无法在 WHERE Col2List = '1,2,3,4,5' 之后添加它们,因为无法识别列,因为 'from Table1' 在括号内。
    • 为什么是LISTAGG? OP 不是在寻找字符串聚合。
    • @LalitKumarB ListAgg 用于按 Col2 分组的聚合值。稍后在 where 语句中使用聚合值。
    • @hkutluay 你没抓住重点。有许多复杂的方法可以实现它。但是,使用LISTAGG 和分隔符等有什么意义?当您只需要一个窗口函数来返回每个组的有序行集时。 LISTAGG 对于字符串聚合很有用。在 OP 的情况下,他会期望单个值而不是分隔列表。
    • @LalitKumarB 查询返回一组行,而不是分隔字符串。 ListAgg 用于过滤行。应该有上千种其他选择来实现这一点,但这是我用来解决这个问题的方法。
    【解决方案3】:

    你也可以在下面使用

    SELECT COL1
        FROM TABLE_NAME
        GROUP BY COL1
        HAVING 
        COUNT(COL1)=5
        AND 
        SUM(
        (CASE WHEN COL2=1 THEN 1 ELSE 0
        END)
        +
        (CASE WHEN COL2=2 THEN 1 ELSE 0
        END)
        +
        (CASE WHEN COL2=3 THEN 1 ELSE 0
        END)
        +
        (CASE WHEN COL2=4 THEN 1 ELSE 0
        END)
        +
        (CASE WHEN COL2=5 THEN 1 ELSE 0
        END))=5
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-13
      • 2014-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-03
      • 2011-11-15
      相关资源
      最近更新 更多