Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

SQL Server - CTE dengan 2 tabel hingga qty dikonsumsi

Anda dapat menggunakan 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

Demo di sini



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tidak dapat membuka tes basis data yang diminta oleh login. Login gagal. Login gagal untuk pengguna 'xyz\ASPNET'

  2. SqlServer.Dmf.dll diperlukan di Cache Majelis Global setelah instalasi aplikasi wpf

  3. Memanggil fungsi C/C++ DLL yang tidak dikelola dari SQL Server 2008

  4. Memasukkan Data SQL Server ke Salesforce dengan Kursor

  5. Jumlah minggu dan sebagian minggu antara dua hari dihitung salah