sql >> データベース >  >> RDS >> Sqlserver

SQL Server - 数量が消費されるまで 2 つのテーブルを持つ CTE

    Recursive CTE :

    ;WITH PurchaseRN AS (
       -- Add row number field to Purchase table
       SELECT szProductID, nQty, szSupplierCode,
              ROW_NUMBER() OVER (PARTITION BY szProductID 
                                 ORDER BY szSupplierCode) AS rn
       FROM Purchase
    ), SalesRN AS (
       -- Add row number field to Sales table
       SELECT szProductID, nQty, szSalesID,
              ROW_NUMBER() OVER (PARTITION BY szProductID 
                                 ORDER BY szSalesID) AS rn
       FROM Sales
    ), ConsumePurchases AS (
       -- Consume 1st Sales record using 1st Purchase record
       SELECT p.szProductID, 
              IIF(p.nQty > s.nQty, s.nQty, p.nQty) AS nQtySales,
              p.szSupplierCode AS SupplierCode, 
              s.szSalesID AS SalesID,         
              -- Propagate un-consumed Purchase/Sales quantities to next recursion level
              IIF(p.nQty > s.nQty, p.nQty - s.nQty, 0) AS pResidue,
              IIF(p.nQty > s.nQty, 0, s.nQty- p.nQty) AS sResidue,
              -- Purchase row number processed by current recursion level
              1 AS prn, 
              -- Sales row number processed by current recursion level
              1 AS srn
       FROM PurchaseRN AS p
       INNER JOIN SalesRN AS s ON p.szProductID = s.szProductID 
       WHERE p.rn = 1 AND s.rn = 1
    
       UNION ALL
    
       SELECT p.szProductID, 
              -- Calculate Sales quantity consumed by current recursion level
              -- If un-consumed Purchase/Sales quantities exist from previous level
              -- then use this instead of nQty field.
              IIF(c.pResidue > 0, 
                 IIF(c.pResidue > s.nQty, s.nQty, c.pResidue),
                 IIF(c.sResidue > 0, 
                   IIF(p.nQty > c.sResidue, c.sResidue, p.nQty),
                   IIF(p.nQty > s.nQty, s.nQty, p.nQty))) AS nQtySales,
              p.szSupplierCode AS SupplierCode, 
              s.szSalesID AS SalesID,         
              x.pResidue,
              x.sResidue, 
              x.prn AS prn, 
              x.srn AS srn
       FROM PurchaseRN AS p
       INNER JOIN SalesRN AS s ON p.szProductID = s.szProductID 
       INNER JOIN ConsumePurchases AS c ON c.szProductID = s.szProductID 
       CROSS APPLY (
          SELECT -- if previous Purchare record is not fully consumed (c.pResidue > 0)
                 -- then stay at the same Purchase record (c.prn), else get next record.
                 CASE 
                    WHEN c.pResidue > 0 THEN c.prn
                    ELSE c.prn + 1
                 END AS prn,
                 -- if previous Sales record is not fully consumed (c.sResidue > 0)
                 -- then stay at the same Sales record (c.srn), else get next record.
                 CASE 
                    WHEN c.sResidue > 0 THEN c.srn 
                    ELSE c.srn + 1
                 END AS srn,             
                 -- calculate Sales quantity left un-cosumed (sResidue) after current record 
                 -- has been processed
                 CASE 
                    WHEN c.sResidue > 0 THEN IIF(c.sResidue - p.nQty > 0, c.sResidue - p.nQty, 0)
                    WHEN c.pResidue > 0 THEN IIF(c.pResidue > s.nQty, 0, s.nQty - c.pResidue)                
                    ELSE IIF(p.nQty > s.nQty, p.nQty - s.nQty, 0)
                 END AS sResidue, 
                 -- calculate Purchase quantity left un-cosumed (pResidue) after current record 
                 -- has been processed
                 CASE 
                    WHEN c.pResidue > 0 THEN IIF(c.pResidue - s.nQty > 0, c.pResidue - s.nQty, 0)
                    WHEN c.sResidue > 0 THEN IIF(p.nQty > c.sResidue, p.nQty - c.sResidue, 0) 
                    ELSE IIF(p.nQty > s.nQty, p.nQty - s.nQty, 0) 
                 END AS pResidue) AS x(prn, srn, sResidue, pResidue)
        -- Continue until there are no more Purchase/Sales records to process
        WHERE p.rn = x.prn AND s.rn = x.srn 
    )
    SELECT szProductID, nQtySales, SupplierCode, SalesID
    FROM ConsumePurchases
    

    デモはこちら



    1. SQL Server 2012 SQLP モジュール - 現在の場所を自動的に変更しますか?

    2. SQLで複数の文字を置き換える方法は?

    3. ループmysqlは、mysqlクエリの外部でphpになります

    4. データストリームを処理するためのMySQLインサートの最適化