【问题标题】:SQL complex view for virtually showing data用于虚拟显示数据的 SQL 复杂视图
【发布时间】:2010-12-21 13:53:14
【问题描述】:

我有一张带有下表的表格。

----------------------------------
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-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,但这需要某种循环来检查一个小时的库存。

【问题讨论】:

  • 你用的是什么数据库引擎?
  • 您的 STOCK_TABLE 的亮点是什么?时间和地点?
  • 数据库引擎是 teradata。对于 stock_table 小时,位置是整数,是主索引的一部分。你能告诉我jey这个词是什么意思吗?
  • virtually show the data 是什么意思?只有我觉得这很有趣吗?似乎他想在有序列表中使用之前显示的图形。

标签: sql database-partitioning ansi-sql


【解决方案1】:

我以前也遇到过类似的问题。确保您需要的数据首先以某种方式进入数据库通常更简单。您也许可以使用定期运行的存储过程来自动化它。

话虽如此,您是否考虑过使用标量子查询尝试 COALESCE()? (或者您的 dbms 支持的任何类似功能。)我会自己尝试并发布 SQL,但我两分钟后要去上班。

【讨论】:

  • 是的,使用所需的旧数据更新表是第一个选项。但是随着业务需求的变化,解决方案架构师挑战这样做......我将尝试使用子查询的 COALESCE。谢谢。
【解决方案2】:

没试过,但按照迈克所说的:

SELECT a.hour
     , COALESCE( a.stock
               , (  select b.stock 
                    from   tbl.b 
                    where  b.hour=a.hour-1   )
               ) "stock"
FROM   tbl a

注意:这会极大地影响性能。

【讨论】:

    【解决方案3】:

    感谢您的回复。我已经针对上述要求尝试了 RECURSIVE VIEW 并给出了正确的结果(我担心大表的 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
    ----------------------------------
    

    然后我们将有一个递归视图,它以递归方式将表与相同的视图连接起来,以使每小时的 Stock 上移一小时并附加数据级别的递增。

    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

    【讨论】:

      【解决方案4】:

      视图最常见的用途是消除复杂性。 例如:

      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 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多