2016-07-06 2 views
0

Я почесываю голову этим одним в течение часа, по-прежнему не могу понять, как выделить сумму платежа в размере 30 долларов США для строк в следующей таблице.sql server распределяет платеж по пунктам

Учитывая, что у меня есть следующие предметы. Отрицательная сумма означает, что клиент имеет задолженность и должен нам эту сумму. Теперь, учитывая, что клиент платит 30 долларов. Мы должны выделить это для элемента.

ItemId        amount sDATE 
BD98E890-C7F8-47F4-9125-A68A88DD178D -10 2016-01-04 00:00:00.000 
7E047DE6-0DB7-4EDB-A751-C43BBD4610E5 -20 2016-01-05 00:00:00.000 
5004AE1F-2A15-47E5-96FF-69A6C7D35521 -10 2016-01-06 00:00:00.000 

за платеж в размере 30 долларов США должен выглядеть следующим образом.

itemId         BeforeAllocation AfterAllocation LeftToAllocate sDate 
BD98E890-C7F8-47F4-9125-A68A88DD178D -10     0    30    2016-01-04 00:00:00.000 
7E047DE6-0DB7-4EDB-A751-C43BBD4610E5 -20     0    20    2016-01-05 00:00:00.000 
5004AE1F-2A15-47E5-96FF-69A6C7D35521 -10     -10    0    2016-01-06 00:00:00.000 

и если клиент оплачивает частичную сумму за $ 25, выпуск должен быть.

itemId         BeforeAllocation AfterAllocation LeftToAllocate sDate 
    BD98E890-C7F8-47F4-9125-A68A88DD178D -10     0    25    2016-01-04 00:00:00.000 
    7E047DE6-0DB7-4EDB-A751-C43BBD4610E5 -20     -5    15    2016-01-05 00:00:00.000 
    5004AE1F-2A15-47E5-96FF-69A6C7D35521 -10     -10    0    2016-01-06 00:00:00.000 

Код:

Create table #temp(ItemId UNIQUEIDENTIFIER , amount INT, sDATE DATETIME) 

INSERT INTO #temp 
     (ItemId, 
      amount, 
      sDATE) 
VALUES ( NEWID(),-10,'2016-01-04'), 
     ( NEWID(),-20,'2016-01-05'), 
     ( NEWID(),-10,'2016-01-06') 


SELECT * FROM (
SELECT 'BD98E890-C7F8-47F4-9125-A68A88DD178D' itemId, -10 BeforeAllocation, 0 AfterAllocation, 30 LeftToAllocate, '2016-01-04 00:00:00.000' sDate  
UNION 
SELECT '7E047DE6-0DB7-4EDB-A751-C43BBD4610E5' itemId, -20 BeforeAllocation, 0 AfterAllocation, 20 LeftToAllocate, '2016-01-05 00:00:00.000' sDate 
UNION 
SELECT '5004AE1F-2A15-47E5-96FF-69A6C7D35521' itemId, -10 BeforeAllocation, -10 AfterAllocation,0 LeftToAllocate, '2016-01-06 00:00:00.000' sDate 
)s 
ORDER BY sdate 

SELECT * FROM (
SELECT 'BD98E890-C7F8-47F4-9125-A68A88DD178D' itemId, -10 BeforeAllocation, 0 AfterAllocation, 25 LeftToAllocate, '2016-01-04 00:00:00.000' sDate  
UNION 
SELECT '7E047DE6-0DB7-4EDB-A751-C43BBD4610E5' itemId, -20 BeforeAllocation, -5 AfterAllocation, 15 LeftToAllocate, '2016-01-05 00:00:00.000' sDate 
UNION 
SELECT '5004AE1F-2A15-47E5-96FF-69A6C7D35521' itemId, -10 BeforeAllocation, -10 AfterAllocation,0 LeftToAllocate, '2016-01-06 00:00:00.000' sDate 
)s 
ORDER BY sdate 

ответ

0
  1. Вычислить выражение BeforeAllocationRT, чтобы записать R unning т OTAL из BeforeAllocation (т.е. сумма BeforeAllocation для этой строки и все предыдущие строки). Если вы используете SQL Server 2012 или более поздние версии, вы можете использовать функции окна, иначе вам понадобится неустойчивое подвыражение - см. this question для получения точных инструкций.

  2. Вычислить выражение для суммы выделить

    SELECT Allocation = CASE 
        WHEN BeforeAllocationRT + @Payment > 0 
         -- pay full amount for this item 
         THEN [email protected] 
        WHEN BeforeAllocationRT + @Payment > @BeforeAllocation 
         -- pay partial amount for this item 
         THEN -(@[email protected]) 
        ELSE 
         -- pay nothing for this item 
         0 
        END 
    , ... 
    
  3. Вычислить выражения для AfterAllocation и LeftToAllocate.

    SELECT 
        AfterAllocation = BeforeAllocation + Allocation 
        ,LeftToAllocate = CASE WHEN [email protected]>0 THEN @Payment-BeforeAllocationRT ELSE 0 END 
        ,... 
    
  4. Объединить шаги 1,2,3 с использованием CTE или подвыражений.

Отказ от ответственности: У меня нет доступа к экземпляру SQL Server прямо сейчас, поэтому никто из них не протестирован.

0

попробовать это,

DECLARE @PaidAmout INT = 30 

;WITH CTE AS 
(
    SELECT ItemId, amount, sDATE, ROW_NUMBER() OVER(ORDER BY sDATE) AS RowNo 
    FROM #temp 
), 
Amount AS 
(
    SELECT ItemId, 
      RowNo, 
      amount AS BeforeAllocation, 
      0 AS AfterAllocation, 
      @PaidAmout AS LeftToAllocate, 
      sDATE, 
      @PaidAmout + Amount AS LeftAmount 
    FROM CTE 
    WHERE RowNo = 1 

    UNION ALL 
    SELECT c.ItemId, 
      c.RowNo, 
      c.amount AS BeforeAllocation, 
      CASE WHEN a.LeftAmount + c.Amount < 0 THEN a.LeftAmount + c.Amount ELSE 0 END AS AfterAllocation, 
      CASE WHEN a.LeftAmount < 0 THEN 0 ELSE a.LeftAmount END AS LeftToAllocate, 
      c.sDATE, 
      a.LeftAmount + c.Amount AS LeftAmount 
    FROM CTE c 
    INNER JOIN Amount a ON a.RowNo + 1 = c.RowNo 
) 

SELECT ItemId, 
     BeforeAllocation, 
     AfterAllocation, 
     LeftToAllocate, 
     sDATE 
FROM Amount 
Смежные вопросы