2012-02-23 11 views
5

Ho una situazione in cui devo prendere una "quantità consumata" da una tabella e applicarla a una seconda tabella che contiene 1 o più righe "lotti raggruppati" di quantità . Non sono sicuro di come descriverlo meglio, ecco cosa voglio dire dal punto di vista tabella:SQL - Sottrai un valore di svuotamento dalle righe

Table Pooled_Lots 
---------------------------- 
Id Pool Lot Quantity 
1 1  1 5 
2 1  2 10 
3 1  3 4 
4 2  1 7 
5 3  1 1 
6 3  2 5 

Table Pool_Consumption 
---------------------------- 
Id PoolId QuantityConsumed 
1 1  17 
2 2  8 
3 3  10 

Ho bisogno di un set di righe risultante da una query SQL che sarebbe simile:

Pool Lot Quantity QuantityConsumed RunningQuantity RemainingDemand SurplusOrDeficit 
1  1 5   17     0    12    NULL 
1  2 10   17     0    2    NULL 
1  3 4   17     2    0    2 
2  1 7   8     0    1    -1 
3  1 1   10     0    9    NULL 
3  2 5   10     0    4    -4 

Quindi, Pool_Consumption.QuantityConsumed deve essere un "valore di svuotamento" sottratto alle righe da Pooled_Lots dove Pool_Consumption.PoolId = Pooled_Lots.Pool. Io non riesco a capire come si potrebbe affermare una query che dice:

  • Se non sull'ultima fila, AmtConsumedFromLot = Quantità - QuantityConsumed se QuantityConsumed < Quantità, altro Quantità
  • Se più righe, QuantityConsumed = QuantityConsumed - Quantità
  • loop fino all'ultima fila
  • Se ultima fila, AmtConsumedFromLot = QuantityConsumed

supponga Id è una chiave primaria, e l'obiettivo è DB SQL 2 005.

Edit: Dal momento che le persone proclamano che sono "non dare abbastanza informazioni, si prega di chiudere questo" Qui è più: C'è NO insieme tanto che il Pool_Consumption attinge, ha bisogno di attingere tutti i lotti dove Pool_Consumption.PoolId = Pooled_Lots.Pool, finché QuantityConsumed non è completamente esaurito o sto sottraendo all'ultimo sottogruppo di Pooled_Lots dove Pool_Consumption.PoolId = Pooled_Lots.Pool

Non so come spiegarlo più. Questa non è una domanda a casa, questo non è un "esercizio di pensiero" inventato. Ho bisogno di aiuto per cercare di capire come sottrarre correttamente QuantityConsumed contro più righe!

+1

non so il motivo per cui le persone sono up-voto a questa domanda, si dispone di alcuni gravi problemi di dati granularità. La tabella 'Pool_Consumption' non specifica il lotto da cui provengono le unità consumate. Inoltre, ho corretto un refuso. -1 – JohnB

+0

Non importa, non mi preoccuperò di correggere tutti i tuoi errori di battitura. Per lo meno, dedica un po 'più di tempo a raccogliere i dati direttamente su questa domanda! Tuttavia, il tuo design è imperfetto per cominciare. (votato per chiudere) – JohnB

+1

@JohnB Questo è ciò a cui sono attualmente confrontato, semplificato il più possibile e senza divulgare dati riservati dal mio lavoro.Invece di essere arrogante e proclamante, sto facendo una domanda stupida e indegna di voti, forse mi puoi illuminare su dove devo aggiungere "granularità" per arrivare a un punto in cui posso produrre più facilmente l'output desiderato? – Irinotecan

risposta

7

lasciato come esercizio al PO: Capire i risultati corretti visti i dati di esempio e che riassume i risultati della query seguente:

-- Create some test data. 
declare @Pooled_Lots as table (Id int, Pool int, Lot int, Quantity int) 
insert into @Pooled_Lots (Id, Pool, Lot, Quantity) values 
    (1, 1, 1, 5), (2, 1, 2, 10), (3, 1, 3, 4), 
    (4, 2, 1, 7), 
    (5, 3, 1, 1), (6, 3, 2, 5) 
declare @Pool_Consumption as table (Id int, Pool int, QuantityConsumed int) 
insert into @Pool_Consumption (Id, Pool, QuantityConsumed) values 
    (1, 1, 17), (2, 2, 8), (3, 3, 10) 

select * from @Pooled_Lots order by Pool, Lot 
select * from @Pool_Consumption order by Pool 

; with Amos as (
    -- Start with Lot 1 for each Pool. 
    select PL.Pool, PL.Lot, PL.Quantity, PC.QuantityConsumed, 
    case 
     when PC.QuantityConsumed is NULL then PL.Quantity 
     when PL.Quantity >= PC.QuantityConsumed then PL.Quantity - PC.QuantityConsumed 
     when PL.Quantity < PC.QuantityConsumed then 0 
     end as RunningQuantity, 
    case 
     when PC.QuantityConsumed is NULL then 0 
     when PL.Quantity >= PC.QuantityConsumed then 0 
     when PL.Quantity < PC.QuantityConsumed then PC.QuantityConsumed - PL.Quantity 
     end as RemainingDemand 
    from @Pooled_Lots as PL left outer join 
     @Pool_Consumption as PC on PC.Pool = PL.Pool 
    where Lot = 1 
    union all 
    -- Add the next Lot for each Pool. 
    select PL.Pool, PL.Lot, PL.Quantity, CTE.QuantityConsumed, 
    case 
     when CTE.RunningQuantity + PL.Quantity >= CTE.RemainingDemand then CTE.RunningQuantity + PL.Quantity - CTE.RemainingDemand 
     when CTE.RunningQuantity + PL.Quantity < CTE.RemainingDemand then 0 
     end, 
    case 
     when CTE.RunningQuantity + PL.Quantity >= CTE.RemainingDemand then 0 
     when CTE.RunningQuantity + PL.Quantity < CTE.RemainingDemand then CTE.RemainingDemand - CTE.RunningQuantity - PL.Quantity 
     end 
    from Amos as CTE inner join 
     @Pooled_Lots as PL on PL.Pool = CTE.Pool and PL.Lot = CTE.Lot + 1 
) 
select *, 
    case 
    when Lot = (select max(Lot) from @Pooled_Lots where Pool = Amos.Pool) then RunningQuantity - RemainingDemand 
    else NULL end as SurplusOrDeficit 
    from Amos 
    order by Pool, Lot 
+0

Grazie! Questo fa esattamente quello che voglio, anche di più! (Anche se penso che lo farò incorporare RunningQuantity e RemainingDemand, poiché sono utili) – Irinotecan

+2

+1 per capire quale fosse la domanda – CodeThug

+2

@TimLarson - Sembrava un tipico problema di selezione dei titoli di magazzino. 13 Sneetches dal ventre stellato. Prendi la prima scatola sullo scaffale Sneetch dal ventre stellato e vedi se ce ne sono abbastanza. Se è così, fantastico. Altrimenti, prendi la scatola successiva. Quando cadi dalla fine del ripiano, prendi la tua pittura e uno stencil e inizia a cercare Sneetches senza stelle su quello di Thar. – HABO

1

(in base a versione 4 di domanda come il mio WiFi è andato giù per un bel po 'di tempo)

(SELECT 
    Pool, 
    SUM(Quantity) as Pool_Quantity 
FROM 
    Pooled_Lots 
GROUP BY 
    Pool) as Pool_Quantity_Table 

Ora avete una tabella con la piscina Quantità arrotolato in un unico valore.

Ora la domanda completa:

SELECT 
    Pool_Consumption.PoolID as Pool, 
    Pool_Quantity_Table.Pool_Quantity as Quantity, 
    Pool_Consumption.QuantityConsumed as AmtConsumedFromLot, 
    (Pool_Quantity_Table.Pool_Quantity - Pool_Consumption.QuantityConsumed) as SurplusOrDefecit 
FROM 
    Pool_Consumption 
INNER JOIN 
    (SELECT 
    Pool, 
    SUM(Quantity) as Pool_Quantity 
    FROM 
    Pooled_Lots 
    GROUP BY 
    Pool) as Pool_Quantity_Table 
ON (Pool_Consumption.PoolID = Pool_Quantity_Table.Pool); 
+0

Grazie per aver trovato il tempo di rispondere a questo, JohnB. Anche se avere i risultati divisi per lotti è un po 'più utile nella mia situazione attuale, questa risposta mi aiuta a capire anche la soluzione al mio problema. Mi scuso per le imprecisioni nella mia tabella dei risultati finali originale, ho pensato di averlo controllato due volte e non l'ho visto fino a quando non hai effettuato la revisione. – Irinotecan

+0

Siete i benvenuti. Mi fa piacere che tu abbia una soluzione al tuo problema! :) – JohnB