T-SQL分组问题

时间:2009-05-19 19:20:18

标签: tsql

每隔一段时间我就有这样的场景,并且永远无法提出最有效的查询来获取信息:

假设我们有一个包含三列的表(A int,B int,C int)。我的查询需要回答这样的问题:“告诉我C列的值是什么,B列的最大值是A = 5。”对于这样的事情,真实世界的场景是“A”是您的用户,“B”是发生的日期,“C”是值,您希望特定用户的最新条目。

我总是最终得到这样的查询:

SELECT
    C
FROM
    MyTable
WHERE
    A = 5
    AND B = (SELECT MAX(B) FROM MyTable WHERE A = 5)

我在一个查询中缺少这样做(与嵌套相反)?某种“拥有”条款?

5 个答案:

答案 0 :(得分:4)

当你只关心1 = A = 5的结果时,BoSchatzberg的回答是有效的。但我怀疑这个问题是一个更普遍的案例的结果。如果您想列出A的每个不同值的最高记录怎么办?

SELECT t1.*
FROM MyTable t1
   INNER JOIN 
     (
       SELECT A, MAX(B)
       FROM MyTable
       GROUP BY A
     )  t2 ON t1.A = t2.A AND t1.B = t2.B

答案 1 :(得分:2)

你可以这样做:

SELECT TOP 1 C
FROM    MyTable
WHERE    A = 5
ORDER BY b DESC

答案 2 :(得分:2)

--
SELECT C
FROM MyTable
INNER JOIN (SELECT A, MAX(B) AS MAX_B FROM MyTable GROUP BY A) AS X
    ON MyTable.A = X.A
    AND MyTable.B = MAX_B
--
WHERE MyTable.A = 5

在这种情况下,第一部分(在评论之间)也可以轻松地移动到视图中以进行模块化或重用。

答案 3 :(得分:1)

我认为你很亲密(你会有什么工作)。您可以使用以下内容:

select C
     , max(B)
  from MyTable
 where A = 5
group by C

答案 4 :(得分:-1)

经过一些测试后,我认为如果不按照你已经做过的方式(即子查询)就可以做到这一点。既然你需要B的最大值而你不能得到C的值而不包括GROUP BY或HAVING子句中的那个,那么子查询似乎是最好的方法。

    create table #tempints (
    a int,
    b int,
    c int
    )

    insert into #tempints values (1, 8, 10)
    insert into #tempints values (1, 8, 10)
    insert into #tempints values (2, 4, 10)
    insert into #tempints values (5, 8, 10)
    insert into #tempints values (5, 3, 10)
    insert into #tempints values (5, 7, 10)
    insert into #tempints values (5, 8, 15)

    /* this errors out with "Column '#tempints.c' is invalid in the select list because it is not contained in either an 
    aggregate function or the GROUP BY clause." */
    select t1.c, max(t1.b)
    from #tempints t1
    where t1.a=5 

    /* this errors with "An aggregate may not appear in the WHERE clause unless it is in a subquery contained in a HAVING 
    clause or a select list, and the column being aggregated is an outer reference." */
    select t1.c, max(t1.b)
    from #tempints t1, #tempints t2
    where t1.a=5 and t2.b=max(t1.b)

    /* errors with "Column '#tempints.a' is invalid in the HAVING clause because it is not contained in either an aggregate 
function or the GROUP BY clause." */
    select c
    from #tempints
    group by b, c
    having a=5 and b=max(b)

    drop table #tempints