我有一张包含下表的表格。
----------------------------------
Hour Location Stock
----------------------------------
6 2000 20
9 2000 24
----------------------------------
因此,这显示了库存数量变化的时间。 现在我的要求是在这个表上创建一个虚拟显示数据的视图(如果库存不是特定小时的htere)。所以应该显示的数据是
----------------------------------
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-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
此查询为没有数据的小时数提供了库存为零的所有小时数。 我们正在研究ANSI sql解决方案,以便它可以在像Teradata这样的数据库上使用。
我在想我是错误地使用分区还是有其他办法。我们尝试使用CASE WHEN但是需要某种循环来检查一些库存的一小时。
答案 0 :(得分:0)
之前我遇到过类似的问题。通常,更容易确保您需要的数据以某种方式进入数据库。您可以使用定期运行的存储过程自动执行它。
话虽如此,您是否考虑过使用标量子查询来尝试COALESCE()? (或者你的dbms支持的任何类似函数。)我自己尝试并发布SQL,但是我将在两分钟内离开工作。
答案 1 :(得分:0)
没试过,但是按照Mike所说的那样:
SELECT a.hour
, COALESCE( a.stock
, ( select b.stock
from tbl.b
where b.hour=a.hour-1 )
) "stock"
FROM tbl a
注意:这会大大影响性能。
答案 2 :(得分:0)
感谢您的回复。我已经尝试了RECURSIVE VIEW以满足上述要求,并且正在给出正确的结果(我担心大表的CPU使用率,因为它是递归的)。所以这是库存表
----------------------------------
Hour Location Stock
----------------------------------
6 2000 20
9 2000 24
----------------------------------
然后我们将在这个表上有一个视图,它将使用Left outer join提供所有12小时的数据。
----------------------------------
Hour Location Stock
----------------------------------
6 2000 20
7 2000 NULL
8 2000 NULL
9 2000 24
----------------------------------
然后我们将有一个递归视图,它以相同的视图递归地连接表,以使每小时的股票移动一小时,并附加增加的数据级别。
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个小时的数据来阻止它进入无限循环)。但我认为某些身体可以将其用于某种层次结构构建。我会寻找你们的其他任何方法的更多回复。谢谢。您可以在以下链接中查看teradata的递归视图。 http://forums.teradata.com/forum/database/recursion-in-a-stored-procedure
答案 3 :(得分:0)
视图最常见的用途是消除复杂性。 例如:
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