【问题标题】:SQL: How to exclude maximum if another column doesn't matchSQL:如果另一列不匹配,如何排除最大值
【发布时间】:2011-09-20 18:32:22
【问题描述】:

我使用的是 Oracle 10g。 我在
SQL - How to select a row having a column with max value

http://jan.kneschke.de/projects/mysql/groupwise-max/

的研究

解决如何处理 max(row),然后找到其他 max(rows) 但是,我还没到。

标准: ID 的 max(enroll_date) 代码必须为“WHEAT”。
我不想要代码为“WHEAT”的最长注册日期。仅当最长注册日期的代码为“WHEAT”时,我才需要该行。

问题:如何编写查询以满足条件?

这不起作用,因为它返回 ID=30, Code = WHEAT 其中 Date 12/25/2001 这不是该 ID 的最大(日期)。

    select ID, code, max(enroll_date)
    from enrollment
    where  CODE = 'WHEAT'
    group by ID, code

这也不起作用,因为它也返回 ID=30,代码 = WHEAT,其中日期 = 2001 年 12 月 25 日。

    select ID, code, max(enroll_date)
    from enrollment
    group by ID, code
    having code='WHEAT'

这是我的桌子

ENROLLMENT
===========================
ID  CODE     ENROLL_DATE
--------------------------
01  WHEAT   <NULL>
01  WHEAT   12/21/2007
01  WHEAT   7/30/2009
30  WHEAT   12/25/2001
30  CHAFF   6/14/2010
72  WHEAT   8/20/2002
72  WHEAT   12/7/2007

 DESIRED RESULT 
 ID    CODE ENROLL_DATE
 ================================
  01     WHEAT  7/30/2009
  72     WHEAT  12/7/2007

【问题讨论】:

    标签: sql oracle oracle10g max groupwise-maximum


    【解决方案1】:

    听起来你想要类似的东西

    SELECT id, 
           code,
           enroll_date
      FROM (SELECT id, 
                   code,
                   enroll_date,
                   rank() over (partition by id 
                                    order by enroll_date desc nulls last) rnk
              FROM enrollment)
     WHERE rnk = 1
       AND code = 'WHEAT'
    

    分析函数RANK 为特定的ID 分配最新的ENROLL_DATE 值1,为该ID 分配下一个最近的ENROLL_DATE 值2,等等。然后您可以参考外部查询中的排名和代码。如果可能有重复,您可能更喜欢使用DENSE_RANKROW_NUMBER 解析函数

    你也可以写查询

    SELECT id, 
           code,
           enroll_date
      FROM (SELECT id, 
                   code,
                   enroll_date,
                   max(enroll_date) over (partition by id) max_enroll_date
              FROM enrollment)
     WHERE enroll_date = max_enroll_date
       AND code        = 'WHEAT'
    

    【讨论】:

    • 很抱歉这个问题可能很愚蠢,但这是一个特定于 Oracle 的解决方案吗?我以前从未见过这个,它有点棒。
    • 不,不是特定于 Oracle 的。例如,在 MS-SQL Server 中:msdn.microsoft.com/en-us/library/ms173454.aspx。它被归类在“聚合函数”下。
    • 您的第一个查询返回 ID=01 的空日期,而不是 max(non-null-date){07/30/2009}。您的第二个查询确实返回了我期望的结果。感谢您的建议。
    • @lamarz - 很抱歉。忘记了我的ORDER BY 中的NULLS LAST 子句。我更新了查询。
    • @Justin Cave:你和 Antlersoft 让我接触了 Oracle-Analytics,让我的工作变得更轻松。我刚刚接触到这些工具可以做的事情的表面,我印象深刻。感谢您的见解和建议。
    【解决方案2】:

    请在 Oracle 文档中查找“分析函数”——这可以满足您的需求。

    基本上,它可以让您对从查询返回的记录分组排序,但仍然可以访问该行中的所有列——您只想检查由enroll_date 排序的组中的第一行是否有代码'小麦'

    【讨论】:

    【解决方案3】:

    这个简单的查询会产生所需的结果

    select * from t where enrolldate=
    (select max(enrolldate) from t as t1
      where t.id=t1.id)
      and t.code='WHEAT'
    

    【讨论】:

    • 这个查询产生了我期待的结果。谢谢
    • 请注意,以这种方式编写查询可能比分析函数方法效率低得多,因为它需要两次而不是一次。
    • @Justin Cave:我同意。我在截止日期前,速度不是问题。这个解决方案有效,我理解它,并且不熟悉分析函数。我现在对分析函数很满意。如果由于效率问题我需要重新访问此代码,我有一个现成的解决方案。这个练习无疑拓宽了我的技能。
    【解决方案4】:

    出于查询的目的,您希望有一个单独的表,其中仅包含最大注册日期行。因此,您可以通过使用子查询来实现:

    SELECT ID, Code, EnrollDate
    FROM enrollment a
    INNER JOIN (SELECT ID, MAX(EnrollDate) AS MaxEnrollDate
                FROM enrollment
                GROUP BY ID) b
    ON (a.ID = b.ID AND a.EnrollDate = b.MaxEnrollDate)
    WHERE Code = 'WHEAT'
    

    希望我做得很好。即使我没有,这个想法也应该奏效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      • 2015-02-11
      • 1970-01-01
      • 2021-08-13
      • 2016-11-22
      相关资源
      最近更新 更多