2009-05-19 6 views
0

をグループ化している間は、私はこのようなシナリオを持っている、との情報に引き出すために、最も効率的なクエリを考え出すことはできません:(T-SQL毎週一回質問

するのは、我々は3つの列を持つテーブルがあるとしましょう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) 

私は(それらをネストではなく)単一のクエリでこれを行うために何をしないのですか?何らかの種類の「所持」条項?

答えて

4

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 
+0

OPには最新のエントリだけが必要なので、おそらくこれを実行する最善の方法です。 –

+0

ありがとう - 私はちょうど非常に似た問題について考え始めました。私はおそらくこれを私自身で取得していただろうが、ここでそれを読むのと同じくらい速くはない.... – RolandTumble

1

私はあなたが近くにいると思います。 、私はこれはそれをあなたはすでにそれをやっている方法(すなわち、副問合せ)を行うことなく行うことができることはないと思うの試験の少し後

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

実際、私はうまくいくとは思わない。私はT-SQLでテストを実行し、Cの "集計関数またはGROUP BY句に含まれていません"というエラーを表示しました。 –

+0

この文がうまくいくことは間違いありません。それはかなりストレートです。誰かがなぜそれがうまくいかないのか私に説明することはできますか? – northpole

+0

ああ...グループで逃した。うん。そうするだろう。 –

-1

:あなたは、次のようなものを使用することができます。あなたはBの最大値が必要で、GROUP BY句またはHAVING句にも含めないでCの値を得ることはできないので、サブクエリが最善の方法と思われます。

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 
2

あなたはこれを行うことができます:あなたが唯一の1つの結果、A = 5を気にする場合

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

素敵な解決策!私はこれがより効率的であるのか、その質問に掲載されたオリジナルであるのだろうかと思います。 – Vizu

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 

この場合には(コメントの間の)最初のセクションはまた、容易にモジュール化または再使用のためにビューに移動させることができます。