事実上データを表示するためのSQL複雑なビュー
-
12-10-2019 - |
質問
次のテーブルのあるテーブルがあります。
----------------------------------
Hour Location Stock
----------------------------------
6 2000 20
9 2000 24
----------------------------------
したがって、これは、量に変化がある時間の一部に対して在庫を示しています。ここで、私の要件は、このテーブルのビューを作成することです。これは、データを事実上表示することです(特定の時間の在庫がない場合)。したがって、表示されるべきデータは次のとおりです
----------------------------------
Hour Location Stock
----------------------------------
6 2000 20
7 2000 20 -- same as hour 6 stock
8 2000 20 -- same as hour 6 stock
9 2000 24
----------------------------------
つまり、特定の時間の間データが存在しなくても、在庫を持っている最後の1時間の在庫を表示する必要があります。そして、私は列に1〜23から利用可能な時間をすべて含む別のテーブルを持っています。
以下に示すように、メソッドごとにパーティションを試しました。しかし、私は自分の要件を成し遂げるために、この周りに何かを見逃していると思います。
SELECT
HOUR_NUMBER,
CASE WHEN TOTAL_STOCK IS NULL
THEN SUM(TOTAL_STOCK)
OVER (
PARTITION BY LOCATION
ORDER BY CURRENT_HOUR ROWS 1 PRECEDING
)
ELSE
TOTAL_STOCK
END AS FULL_STOCK
FROM
(
SELECT HOUR_NUMBER AS HOUR_NUMBER
FROM HOURS_TABLE -- REFEERENCE TABLE WITH HOURS FROM 1-23
GROUP BY 1
) HOURS_REF
LEFT OUTER JOIN
(
SEL CURRENT_HOUR AS CURRENT_HOUR
, STOCK AS TOTAL_STOCK
,LOCATION AS LOCATION
FROM STOCK_TABLE
WHERE STOCK<>0
) STOCKS
ON HOURS_REF.HOUR_NUMBER = STOCKS.CURRENT_HOUR
このクエリは、データなしで時間のnullとして在庫を備えたすべての時間を与えています。 Teradataなどのデータベースで使用できるように、ANSI SQLソリューションを検討しています。
私は誤ってパーティションを使用していると考えています。私たちはケースで試しましたが、それはある種のループを必要として、在庫で1時間再度チェックします。
解決 3
ご回答ありがとうございます。私は上記の要件について再帰的な見解を試しましたが、正しい結果をもたらしています(再帰的であるため、大きなテーブルのCPU使用について恐れています)。ここにストックテーブルがあります
----------------------------------
Hour Location Stock
----------------------------------
6 2000 20
9 2000 24
----------------------------------
次に、このテーブルにビューがあり、左外の結合を使用して12時間すべてのデータを提供します。
----------------------------------
Hour Location Stock
----------------------------------
6 2000 20
7 2000 NULL
8 2000 NULL
9 2000 24
----------------------------------
次に、同じビューでテーブルに再帰的に結合する再帰ビューがあり、各1時間の在庫を1時間上げて、データレベルのデータを増加させます。
REPLACE RECURSIVE VIEW HOURLY_STOCK_VIEW
(HOUR_NUMBER,LOCATION, STOCK, LVL)
AS
(
SELECT
HOUR_NUMBER,
LOCATION,
STOCK,
1 AS LVL
FROM STOCK_VIEW_WITH_LEFT_OUTER_JOIN
UNION ALL
SELECT
STK.HOUR_NUMBER,
THE_VIEW.LOCATION,
THE_VIEW.STOCK,
LVL+1 AS LVL
FROM STOCK_VIEW_WITH_LEFT_OUTER_JOIN STK
JOIN
HOURLY_STOCK_VIEW THE_VIEW
ON THE_VIEW.HOUR_NUMBER = STK.HOUR_NUMBER -1
WHERE LVL <=12
)
;
最初に左外の結合ビューから選択し、それを作成している左外の結合ビューと結合し、作成している同じビューで結合され、データが来るレベルを提供します。
次に、このビューから最小レベルでデータを選択します。
SEL * FROM HOURLY_STOCK_VIEW
WHERE
(
HOUR_NUMBER,
LVL
)
IN
(
SEL
HOUR_NUMBER,
MIN(LVL)
FROM HOURLY_STOCK_VIEW
WHERE STOCK IS NOT NULL
GROUP BY 1
)
;
これは正常に動作し、結果を与えています
----------------------------------
Hour Location Stock
----------------------------------
6 2000 20
7 2000 20 -- same as hour 6 stock
8 2000 20 -- same as hour 6 stock
9 2000 24
10 2000 24
11 2000 24
12 2000 24
----------------------------------
これは、再帰作業を取得するために大きなテーブルに巨大なCPUを取ることを知っています(12時間のデータが無限ループに入るのを止めるために12時間のデータが必要であるため、再帰を12レベルに制限しています)。しかし、ある種の階層ビルにこれを使用できると考えました。利用可能な他のアプローチについて、皆さんからのいくつかの応答を探します。ありがとう。 Teradataの以下のリンクで再帰ビューを見ることができます。http://forums.teradata.com/forum/database/recursion-in-a-stored-procedure
他のヒント
以前にも同様の問題に遭遇しました。しばしば、必要なデータがどうにかしてデータベースに入ることを確認するのが簡単です。定期的に実行されるストアドプロシージャで自動化できる場合があります。
そうは言っても、スカラーサブクエリでcoales()を試すことを考えましたか? (またはDBMSがサポートする同様の機能。)私はそれを自分で試してSQLを投稿しますが、2分で仕事のために出発します。
試したことはありませんが、マイクが言ったことの線に沿って:
SELECT a.hour
, COALESCE( a.stock
, ( select b.stock
from tbl.b
where b.hour=a.hour-1 )
) "stock"
FROM tbl a
注:これはパフォーマンスに大きな影響を与えます。
視野の最も一般的な用途は、複雑さの除去です。例えば:
CREATE VIEW FEESTUDENT
AS
SELECT S.NAME,F.AMOUNT FROM STUDENT AS S
INNER JOIN FEEPAID AS F ON S.TKNO=F.TKNO
今やる SELECT
:
SELECT * FROM FEESTUDENT