簡體   English   中英

SQL聯接庫存盤點表至日期表

[英]SQL Join Inventory Count Table to Date table

我有一個運行中的不同產品的庫存表,該表記錄每筆交易后的庫存數量。 交易並非每天都會發生,因此該表沒有每日運行的計數。

我需要列出每種產品的所有日期,以便可以對一段時間內的計數求和並取平均值。

庫存

DATE        ID  Qty Count
2014-05-13  123 12  12
2014-05-19  123 -1  11
2014-05-28  123 -1  10
2014-05-29  123 -3  7
2014-05-10  124 5   5
2014-05-15  124 -1  4
2014-05-21  124 -1  3
2014-05-23  124 -3  0

我有一個表,其中包含加入日期,但是我不確定如何使缺失的日期加入多個產品。

我需要如下查詢。 它需要返回所選期間內的計數,但還應包括其間的日期。

DATE        ID  Qty Count
2013-05-01  123 0   0
2013-05-02  123 0   0
2013-05-03  123 0   0
2013-05-04  123 0   0
2013-05-05  123 0   0
2013-05-06  123 0   0
2013-05-07  123 0   0
2013-05-08  123 0   0
2013-05-09  123 0   0
2013-05-10  123 0   0
2013-05-11  123 0   0
2013-05-12  123 0   0
2014-05-13  123 12  12
2013-05-14  123 0   12
2013-05-15  123 0   12
2013-05-16  123 0   12
2013-05-17  123 0   12
2013-05-18  123 0   12
2014-05-19  123 -1  11
2013-05-20  123 0   11
2013-05-21  123 0   11
2013-05-22  123 0   11
2013-05-23  123 0   11
2013-05-24  123 0   11
2013-05-25  123 0   11
2013-05-26  123 0   11
2013-05-27  123 0   11
2014-05-28  123 -1  10
2014-05-29  123 -3  7
2013-05-30  123 0   7
2013-05-31  123 0   7
2013-05-01  124 0   0
2013-05-02  124 0   0
2013-05-03  124 0   0
2013-05-04  124 0   0
2013-05-05  124 0   0
2013-05-06  124 0   0
2013-05-07  124 0   0
2013-05-08  124 0   0
2013-05-09  124 0   0
2014-05-10  124 5   5
2014-05-11  124 0   5
2014-05-12  124 0   5
2014-05-13  124 0   5
2014-05-14  124 0   5
2014-05-15  124 -1  4
2014-05-16  124 0   4
2014-05-17  124 0   4
2014-05-18  124 0   4
2014-05-19  124 0   4
2014-05-20  124 0   4
2014-05-21  124 -1  3
2014-05-22  124 0   3
2014-05-23  124 -3  0
2014-05-24  124 0   0
2014-05-25  124 0   0
2014-05-26  124 0   0
2014-05-27  124 0   0
2014-05-28  124 0   0
2014-05-29  124 0   0
2014-05-30  124 0   0
2014-05-31  124 0   0

使用inv join inv可以建立至少31行並構造一個31天的表。 然后加入id,最后加入原始表。

select a.d, a.id, a.qty,
  if(a.id=@lastid, @count:=@count+a.qty, @count:=a.count) `count`,
  @lastid:=a.id _lastid
from (
  select a.d, b.id, ifnull(c.qty, 0) qty, ifnull(c.count, 0) `count`
  from (
    select adddate('2014-05-01', @row) d, @row:=@row+1 i
    from inv a
    join inv b
    join (select @row := 0) c
    limit 31) a
  join (
    select distinct id
    from inv) b
  left join inv c on a.d = c.date and b.id = c.id
  order by b.id, a.d) a
join (select @count := 0, @lastid := 0) b;

小提琴

這是需要的步驟:

  1. 獲取兩個給定日期之間的所有日期。
  2. 獲取每個ID的初始庫存。 這是:獲取該ID在給定開始日期或之后的第一個日期,讀取該記錄的庫存並減去其交易數量。
  3. 對於每個日期,請獲取之前的庫存。 如果有該日期的記錄,則添加其交易數量並將結果與​​其庫存數量進行比較。 如果值不匹配,則會引發錯誤。 (這是因為您冗余地存儲了數據;記錄的數量必須等於前一個記錄的數量加上它自己的交易數量。但是數據始終會不一致,因此最好檢查一下。)顯示新庫存和與先前庫存的差異。

通常使用日期的遞歸CTE,最多使用KEEP DENSE_RANK函數的所有初始存貨的派生表以及使用LAG函數查看先前記錄的方法來實現所有這些目的。

  • MySQL不支持遞歸CTE-或完全不支持CTE。 您可以使用足夠大的表和一個變量來模擬它。
  • MySQL不支持KEEP DENSE_RANK函數。 您可以使用另一個派生表代替,首先查找每個ID的最短日期。
  • MySQL不支持LAG功能。 您可以改為在MySQL中使用變量。

話雖如此,我建議改用編程語言(Java,C#,PHP等)。 您只需使用SQL選擇原始數據,使用循環,然后簡單地對每個記錄進行所有處理。 這比構建一個非常復雜的查詢來完成所有需要的操作要方便得多(而且可讀性強)。 您可以在SQL中執行此操作,甚至可以在MySQL中執行; 我只是不推薦。

我最終用來解決此問題的SQL結合了@Fabricators答案(這確實是正確的答案)和我的編輯。

我最終使用現有表創建日期行,而不是交叉聯接。 對於使用的產品數量,交叉連接的性能較差。

SELECT
POSTDATE,
IF(@PROD_ID = PRODUCT_ID, @NEW := 0, @NEW := 1) AS New_Product,
(@PROD_ID := PRODUCT_ID) AS PRODUCT_ID,
QUANTITY,
IF(@NEW = 1, @INVENTORY := QUANTITY, @INVENTORY := @INVENTORY+QUANTITY) AS 'Count'
FROM (
    (
        SELECT
        POSTDATE,
        PRODUCT_ID,
        QUANTITY
        FROM
        inventory
    )
    UNION ALL
    (
        SELECT
        dateslist_sub.TransDate AS POSTDATE,
        productlist_sub.PRODUCT_ID,
        0 AS QUANTITY,
        FROM
        (
            SELECT
            TransDate
            FROM
            (
                SELECT
                adddate('2013-05-01', @row) AS TransDate,
                @row:=@row+1 i
                FROM
                any_table,
                (SELECT @row := 0) row
            ) datestable
            WHERE
            TransDate <= CURDATE()
        ) dateslist_sub
        cross join (
            SELECT
            PRODUCT_ID
            FROM
            products_table
            ORDER BY
            PRODUCT_ID ASC
        ) productlist_sub
        ORDER BY
        productlist_sub.PRODUCT_ID ASC,
        dateslist_sub.TransDate ASC
    )
    ORDER BY
    PRODUCT_ID ASC,
    POSTDATE ASC
) daily_rows_sub

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM