0

アイテムの評価を表す次の表があります。

ITEM             REFERENCEDATE     VALUATION
------------------------------------------------
A                25/01/2012        25.35
A                26/01/2012        51.35
B                25/01/2012        25.00

編集:(ITEM、REFERENCEDATE)は一意のインデックスです。

目標は、アイテムのセットの最新の評価を取得することです。つまり、次のようなものを返すSQLリクエストを作成しようとしています。

ITEM             REFERENCEDATE     VALUATION
------------------------------------------------
A                26/01/2012        51.35
B                25/01/2012        25.00

GROUP BYのチュートリアルを流して、私は試してみました

SELECT A.ITEM, A.VALUATION, MAX(A.REFERENCEDATE)
FROM VALUATIONS A
GROUP BY A.ITEM

SQLサーバーが、現在の結果行に表示されているITEMのA.REFERENCEDATEの最大値を実現する行にA.VALUATIONが必要であることを理解してくれることを期待しています。

しかし、代わりに、この不快なエラーメッセージが表示されます。

Column 'VALUATIONS.VALUATION' is invalid in the select list because it is not contained 
in either an aggregate function or the GROUP BY clause.

REFERENCEDATEの最大値に達したVALUATIONを使用する必要があることをどのように示すことができますか?

注:少なくともOracleとSQLServerで機能するソリューションが必要です

編集:あなたの助けをみんなに感謝します。SELECT ...GROUPBYリクエストを1つだけ使用して逃げようとして穴に閉じ込められました。今、私は同じ考えを明確にする2つのアプローチがあることがわかります。

  1. すべてのアイテム/最大(日付)のカップルを返す他の独立したリクエストの結果を使用してJOINを作成する
  2. サブリクエストを使用すると、アイテムごとに異なる値を持つwhere句が生成されます。

誰かが一方を他方よりも好む理由(または理由へのポインタ)を提供できますか?

4

5 に答える 5

4
Select V.Item, V.ReferenceDate, V.Valuation
From Valuations As V
Where V.ReferenceDate = (
                        Select Max(V1.ReferenceDate)
                        From Valuations As V1
                        Where V1.Item = V.Item
                        )

SQL フィドルのバージョン

あなたの編集に応じて、どのアプローチがより良いパフォーマンスを発揮するかを確実に知る唯一の方法は、各クエリの実行計画を評価することです。最速のアプローチを決定する要因は数多くありますが、確かに DBMS 自体がそれらの要因の 1 つです。優れたクエリ エンジンは、アプローチに関係なく、同じまたは類似の実行プランを推測できる必要があります。とはいえ、派生テーブルを使用する (つまり、アプローチ #1) と、クエリ エンジンに対しては (クエリのリーダーに対してはあまり明示的ではありませんが) もう少し明確になる可能性があり、パフォーマンスが向上する可能性があります。多くの場合、派生テーブルは相関サブクエリよりも優れたパフォーマンスを発揮します (私の解決策とあなたのアプローチ #2)。ただし、変更を裏付ける証拠が得られるまで、アプローチを変更しません。また、

于 2012-11-13T20:09:27.683 に答える
3

MySQL 以外のほぼすべてのデータベースを使用している場合、答えはランキング関数を使用することです。特に、row_numberあなたが探していることを行います:

select ITEM, REFERENCEDATE, VALUATION
from (select t.*
             row_number() over (partition by item order by referencedate desc) as seqnum
      from t
     ) t
where seqnum = 1 and
      item in (<your list of items>)

行番号は、各項目のレコードにシーケンス番号を割り当てます。最大の基準日は 1 から始まり、次の最大の基準日は 2 というようになります (order by 句に基づく)。seqnum = 1 の最初のものが必要です。

于 2012-11-13T20:53:27.383 に答える
2
select a.item, a.valuation, a.referencedate
from valuations a
  join (select a2.item, max(referencedate) as max_date
        from valuations a2
        group by a2.item
  ) b ON a.item = b.item and a.referencedate = b.max_date
于 2012-11-13T20:15:15.210 に答える
1

これを試して:

SELECT A.ITEM, MAX(A.VALUATION), A.REFERENCEDATE
FROM VALUATIONS A
JOIN 
(
    SELECT A.ITEM, MAX(A.REFERENCEDATE) AS REFERENCEDATE
    FROM VALUATIONS A
    GROUP BY A.ITEM
) B ON A.ITEM = B.ITEM AND A.REFERENCEDATE = B.REFERENCEDATE
GROUP BY A.ITEM, A.REFERENCEDATE

max(REFERENCEDATE) を保持する列から MAX 値を選択します。1 つの列だけが最大になると予想される場合は、選択できる列から選択するだけです。

于 2012-11-13T20:08:51.367 に答える
-1

これはおそらく必要なコードです:

Select  *
    From    ItemValues      As  A
    Inner   Join
        ItemValues      As  MaxValuedItem
    On  MaxValuedItem.Id    =   (
        Select  Top 1
            B.Id
            From    ItemValues  As  B
            Where   B.Item_Id   =   A.Item_Id
            Order   By      B.Valuation Desc
    )

同じアイテムの最大値を持つレコードを参照する"join"テーブル自体でを使用する必要があります。

于 2012-11-13T20:12:51.537 に答える