MAX()OVER PARTITION BY関数を使用して、会社が購入した特定の部品の最新の領収書を評価しようとしています。以下は、昨年のいくつかの部分の情報の表の例です。
| VEND_NUM | VEND_NAME | RECEIPT_NUM | RECEIPT_ITEM | RECEIPT_DATE |
|----------|--------------|-------------|----------|--------------|
| 100 | SmallTech | 2001 | 5844HAJ | 11/22/2017 |
| 100 | SmallTech | 3188 | 5521LRO | 12/31/2017 |
| 200 | RealSolution | 5109 | 8715JUI | 05/01/2017 |
| 100 | SmallTech | 3232 | 8715JUI | 11/01/2017 |
| 200 | RealSolution | 2101 | 4715TEN | 01/01/2017 |
ご覧のとおり、3行目と4行目は、同じ部品番号の2つの異なるベンダーを示しています。
これが私の現在のクエリです:
WITH
-- various other subqueries above...
AllData AS
(
SELECT VEND_NUM, VEND_NAME, RECEIPT_NUM, RECEIPT_ITEM, RECEIPT_DATE
FROM tblVend
INNER JOIN tblReceipt ON VEND_NUM = RECEIPT_VEND_NUM
WHERE
VEND_NUM = '100' OR VEND_NUM = '200' AND RECEIPT_DATE >= '01-Jan-2017'
),
SELECT MAX(RECEIPT_DATE) OVER PARTITION BY(RECEIPT_ITEM) AS "Recent Date", RECEIPT_ITEM
FROM AllData
私の返品セットは次のようになります。
| Recent Date | RECEIPT_ITEM |
|-------------|--------------|
| 11/22/2017 | 5844HAJ |
| 12/31/2017 | 5521LRO |
| 11/01/2017 | 8715JUI |
| 11/01/2017 | 8715JUI |
| 01/01/2017 | 4715TEN |
ただし、次のようになります。
| Recent Date | RECEIPT_ITEM |
|-------------|--------------|
| 11/22/2017 | 5844HAJ |
| 12/31/2017 | 5521LRO |
| 11/01/2017 | 8715JUI |
| 01/01/2017 | 4715TEN |
誰かが私が間違っていることについてアドバイスを提供できますか?必要な行だけを表示するのではなく、単に最新の日付を置き換えているようです。
最終的には、テーブルをこのようにしたいと思います。ただし、これを可能にするためにMAX()またはMAX()OVER PARTITION BY()関数を適切に使用する方法がわかりません。
| VEND_NUM | VEND_NAME | RECEIPT_NUM | RECEIPT_ITEM | RECEIPT_DATE |
|----------|--------------|-------------|----------|--------------|
| 100 | SmallTech | 2001 | 5844HAJ | 11/22/2017 |
| 100 | SmallTech | 3188 | 5521LRO | 12/31/2017 |
| 100 | SmallTech | 3232 | 8715JUI | 11/01/2017 |
| 200 | RealSolution | 2101 | 4715TEN | 01/01/2017 |
ウィンドウ関数ROW_NUMBER() OVER (PARTITION BY receipt_item ORDER BY receipt_date DESC)
を使用して、各行にシーケンス番号を割り当てます。 receipt_date
の最新のreceipt_item
の行には1の番号が付けられます。
WITH
-- various other subqueries above...
AllData AS
(
SELECT VEND_NUM, VEND_NAME, RECEIPT_NUM, RECEIPT_ITEM, RECEIPT_DATE,
ROW_NUMBER() OVER (PARTITION BY RECEIPT_ITEM ORDER BY RECEIPT_DATE DESC ) AS RN
FROM tblVend
INNER JOIN tblReceipt ON VEND_NUM = RECEIPT_VEND_NUM
WHERE
VEND_NUM IN ( '100','200') AND RECEIPT_DATE >= '01-Jan-2017'
)
SELECT VEND_NUM, VEND_NAME, RECEIPT_NUM, RECEIPT_ITEM, RECEIPT_DATE
FROM AllData WHERE RN = 1
ここにいくつかの問題があります。 1つは、集計関数MAX()
を分析関数(Oracleがウィンドウ関数と呼ぶのに役立つ)として使用するための構文は次のようになります。
_MAX(receipt_date) OVER ( PARTITION BY receipt_item )
_
(括弧の位置に注意してください)。次に、目的の結果セットから、実際にはウィンドウ関数は必要なく、集計する必要があります。ウィンドウ(または分析)関数は、常にパーティション内の各行の行を返します。それはまさにそれが機能する方法です。だから私はあなたが欲しいのはこれだと思います:
_WITH
-- various other subqueries above...
AllData AS
(
SELECT VEND_NUM, VEND_NAME, RECEIPT_NUM, RECEIPT_ITEM, RECEIPT_DATE
FROM tblVend
INNER JOIN tblReceipt ON VEND_NUM = RECEIPT_VEND_NUM
WHERE ( VEND_NUM = '100' OR VEND_NUM = '200' ) AND RECEIPT_DATE >= DATE'2017-01-01'
)
SELECT VEND_NUM, VEND_NAME, RECEIPT_NUM, RECEIPT_ITEM, MAX(RECEIPT_DATE)
FROM AllData
GROUP BY VEND_NUM, VEND_NAME, RECEIPT_NUM, RECEIPT_ITEM;
_
OR
がAND
よりも優先されるため(IN ('100','200')
を使用する方が良い場合があります)、OR
条件を括弧で囲むなど、上記にいくつかの小さな変更を加えました(したがって、クエリはVEND_NUM = '100' OR ( VEND_NUM = '200' RECEIPT_DATE >= DATE'2017-01-01' )
...しかし、多分それはあなたが望んでいたことですか?).
これは、質問の元のバージョンに答えます。
where
句はおそらく次のようになります。
WHERE VEND_NUM IN ('100', '200') AND RECEIPT_DATE >= DATE '2017-01-01'
あなたが望むものが単純である可能性は十分にあります:
SELECT DISTINCT RECEIPT_DATE, RECEIPT_ITEM
FROM tblVend INNER JOIN
tblReceipt
ON VEND_NUM = RECEIPT_VEND_NUM
WHERE VEND_NUM IN ('100', '200') AND RECEIPT_DATE >= DATE '2017-01-01';
少なくとも、これはあなたが返したいものを返します。