2012-02-23 8 views
5

Tengo una situación donde necesito tomar una "cantidad consumida" de una tabla, y aplicarla a una segunda tabla que tiene 1 o más filas que son "lotes agrupados" de cantidades . No estoy seguro de cómo describirlo mejor, esto es lo que quiero decir desde una perspectiva tabla:SQL - Restando un valor de agotamiento de las filas

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 

Necesito un conjunto de filas resultante de una consulta SQL que se vería así:

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 

Por lo tanto, Pool_Consumption.QuantityConsumed debe ser un "valor de agotamiento" restado en las filas de Pooled_Lots donde Pool_Consumption.PoolId = Pooled_Lots.Pool. No puedo imaginar cómo le indicará una consulta que dice:

  • Si no en la última fila, AmtConsumedFromLot = Cantidad - QuantityConsumed si QuantityConsumed < Cantidad, de lo contrario Cantidad
  • Si más filas, QuantityConsumed = QuantityConsumed - Cantidad
  • bucle hasta última fila
  • Si última fila, AmtConsumedFromLot = QuantityConsumed

Supongamos Id es una clave principal, y el objetivo es DB SQL 2 005.

Editar: Dado que las personas están proclamando que soy "no dar suficiente información, por favor, cierre esta" Aquí hay más: existe NO mucho que el conjunto Pool_Consumption extrae de, tiene que sacar de todos los lotes donde Pool_Consumption.PoolId = Pooled_Lots.Pool, hasta QuantityConsumed esté totalmente agotada o estoy restando contra el último subconjunto de filas en las que Pooled_Lots Pool_Consumption.PoolId = Pooled_Lots.Pool

no sé qué más para explicar esto. Esta no es una pregunta para la tarea, no es un "ejercicio mental" inventado. ¡Necesito ayuda para tratar de descubrir cómo restar correctamente QuantityConsumed en varias filas!

+1

no sé por qué las personas son hasta derecho a voto a esta pregunta, usted tiene algunos problemas graves de granularidad de datos. La tabla 'Pool_Consumption' no especifica de qué lote provienen las unidades consumidas. Además, arreglé un error tipográfico. -1 – JohnB

+0

No importa, no voy a molestarme en arreglar todos tus errores tipográficos. Por lo menos, ¡dedique un poco más de tiempo a obtener los datos correctos sobre esta pregunta! Sin embargo, su diseño es defectuoso para comenzar. (votó para cerrar) – JohnB

+1

@JohnB Esto es lo que actualmente estoy enfrentando, simplificado tanto como puedo y sin revelar datos confidenciales de mi trabajo.En lugar de ser arrogante y proclamar que estoy haciendo una pregunta estúpida que no merece votos, tal vez me puede aclarar dónde debo agregar "granularidad" para llegar a un punto en el que pueda producir la producción deseada más fácilmente. – Irinotecan

Respuesta

7

deja como ejercicio para el OP: Averiguar los resultados correctos dados los datos de la muestra y el resumen de los resultados de la consulta siguiente:

-- 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

¡Gracias! Esto hace exactamente lo que quiero, ¡aún más! (Aunque creo que lo haré incorporar RunningQuantity y RemainingDemand, ya que son útiles) – Irinotecan

+2

+1 para averiguar cuál era la pregunta – CodeThug

+2

@TimLarson - Parecía un típico problema de selección de stock en el almacén. Necesito 13 Sneetches de vientre estrellado. Coge la primera caja en el estante Sneetch de vientre estrellado y mira si hay suficiente. Si es así, genial. Si no, agarra el siguiente cuadro. Cuando te caes del extremo del estante, tomas tu pintura y una plantilla y comienzas a buscar Sneetches sin estrellas sobre thar. – HABO

1

(basado en la versión 4 de la pregunta como mi WiFi bajó desde hace bastante tiempo)

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

Ahora usted tiene una tabla con la piscina Cantidad enrollado en un solo valor.

Ahora la consulta 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

Gracias por tomarse el tiempo para responder a esto, JohnB. Aunque tener los resultados divididos por lotes es un poco más útil en mi situación actual, esta respuesta me ayuda a entender la solución a mi problema también. Me disculpo por las imprecisiones en la tabla de resultados finales original, pensé que lo había comprobado dos veces y no lo vi hasta que hizo la revisión. – Irinotecan

+0

Eres bienvenido. ¡Me alegro de que hayas encontrado una solución a tu problema! :) – JohnB

Cuestiones relacionadas