【问题标题】:How to return distinct records based on two different values如何根据两个不同的值返回不同的记录
【发布时间】:2012-04-04 06:13:14
【问题描述】:

我在名为 MY_ATTRIBUTES 的 Oracle 表中有以下数据示例:

Date        Emp_No  Attribute
-----------------------------------------------------
01/04/2012  1234567 APPLE
01/04/2012  1234567 ORANGE
01/04/2012  1234567 PINEAPPLE
01/04/2012  1234567 BANANA
01/04/2012  8888888 APPLE
01/04/2012  8888888 ORANGE
01/04/2012  2222222 APPLE
01/04/2012  2222222 ORANGE
01/04/2012  2222222 PINEAPPLE

根据上面的示例数据,我只需要返回仅使用 Date 和 Emp_No 的不同记录,其中这些记录包含同时具有“APPLE”和“PINEAPPLE”属性的数据

所以根据这个标准,我希望只有以下两条结果记录,即:

01/04/2012  1234567
01/04/2012  2222222

我希望编写一个 Oracle SQL 查询,它将根据所描述的条件返回此结果集。

我还应该指出,我需要将此 SQL 查询用作主 SELECT 的子查询。

【问题讨论】:

  • 您的问题包含答案...当您区分记录时使用 distinct 函数...例如 Select distinct from table where.....
  • 明白你在说什么,但我不知道如何提取属性为 APPLE 和 PINEAPPLE 的记录。
  • 你可以使用 IN 函数..或 UNION..Select distinct date,emp_no from (select * from table where attribute = apple union select * from table where attribute = apple)....跨度>

标签: sql oracle oracle10g


【解决方案1】:

试试

SELECT DISTINCT A.Date, A.Emp_no 
FROM (SELECT * FROM MY_ATTRIBUTES WHERE ATTRIBUTE = 'APPLE') A 
INNER JOIN (SELECT * FROM MY_ATTRIBUTES WHERE ATTRIBUTE = 'PINEAPPLE' ) B ON B.Date = A.Date AND B.Emp_No = A.Emp_No 

【讨论】:

    【解决方案2】:

    可能有更有效的方法,但这应该可行:

    SELECT DISTINCT DATE, EMP_NO
    FROM   (
        SELECT DATE, EMP_NO
        FROM   MY_ATTRIBUTES
        WHERE  ATTRIBUTE = 'APPLE'
        INTERSECT
        SELECT DATE, EMP_NO
        FROM   MY_ATTRIBUTES
        WHERE  ATTRIBUTE = 'PINEAPPLE'
    );
    

    【讨论】:

    • 这一切都很好,但我现在发现这样做的性能问题 - 关于如何加速/调整查询的任何想法?
    • INTERSECT 应该提供一组独特的组合,因此不需要 DISTINCT 子句,这会导致额外的排序。
    • @APC good catch(voted comment) 但我认为新的 Oracle 优化器知道这一点,不会进行两次排序。我没有时间测试它...
    【解决方案3】:

    如果没有重复项(例如,同一日期的 2 个 APPLES 和 emp),这可能会更有效,因为没有连接:

    SELECT DATE, EMP_NO 
    FROM MY_ATTRIBUTES
    WHERE ATTRIBUTE = 'APPLE' OR  ATTRIBUTE = 'PINEAPPLE'
    GROUP BY DATE, EMP_NO
    HAVING COUNT(*) = 2
    

    【讨论】:

    • 感谢 barju,但我实际上将此查询要求用作子查询的一部分,不幸的是我无法在子查询中使用 GROUP BY。如果用作子查询有解决方法,会很感激吗?谢谢。
    • 它必须是子查询吗?也许您应该发布整个查询,以便我们可以解决这个问题..
    【解决方案4】:

    主题的变体:

    with cte as 
     ( select date, empno, attribute
       from my_attributes
       where attribute in ('PINEAPPLE', 'APPLE') )
    select  *
    from (  select date, emp_no
            from cte
            where attribute = 'PINEAPPLE'
            intersect
            select date, emp_no
            from cte
            where attribute = 'APPLE' )
    

    任何这些解决方案的性能都取决于 ATTRIBUTE 的选择性。如果您的碗里只有六种水果,那么您将看到整张桌子,并且调整这些水果的选择有限。另一方面,如果该列是一个充满水果味的蔬菜水果商(比如 150 多个不同的值),那么您应该从索引中获得回报。但这仍然取决于分布和偏差:如果 ATTRIBUTE 是 90% 的苹果和菠萝,您可能看不到索引的任何好处:在这种情况下,全表扫描仍然是更好的选择。

    tl;dr

    调整很困难

    【讨论】:

      【解决方案5】:

      您可以尝试以下方法:

      SELECT DATE, EMP_NO FROM YOUR_TABLE WHERE ATTRIBUTE = 'APPLE' OR ATTRIBUTE = 'PINEAPPLE' GROUP BY DATE, EMP_NO HAVING COUNT(*) = 2;

      【讨论】:

      • @FlorinGhita 答案是否与实际答案不同?是的,你可以说它的风格不同
      • 我不明白你在说什么。你的答案和barsju的一样。除了格式之外,他已经说过您的回复(比您早 4 小时)的内容。同一件事有两个答案是没有用的。
      • 您需要清楚地了解我所说的哪个答案是正确的答案,无论它是否与barsju's 或100 人的答案相匹配都无所谓好吗?而不是和我一起玩,你应该回答这个问题并放松一下好吗?
      【解决方案6】:
      SELECT DISTINCT DATE, EMP_NO
      WHERE  ATTRIBUTE IN('APPLE','PINEAPPLE')
      

      【讨论】:

      • 这将提供 DATE、EMP_NO 组合在任一属性上匹配的结果。 OP 只需要对两者都有记录的组合。
      【解决方案7】:
      SELECT DISTINCT Emp_No, Date
      FROM (
        SELECT *
        FROM MY_ATTRIBUTES m
        WHERE m.Attribute IN ('Apple','Pineapple')
        )
      LIMIT 2
      ORDER BY Emp_No
      

      【讨论】:

      • 这将提供 DATE、EMP_NO 组合在任一属性上匹配的结果。 OP 只需要对两者都有记录的组合。此外,LIMIT 不是 Oracle 语法,但即使是它也不会产生正确的效果。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多