MIGRACIÓN DE T-SQL de acceso a SQL Acceso de trabajo con un problema al escribir el reemplazo del caso para IIF
Pregunta
Tengo dos tablas bmreports_fpn_curves y bmreports_boa_curves que consiste en un nombre, datetime, período y valor, por ejemplo:
BM_UNIT_NAME RunDate Period FPN (or BOA)
T_DRAXX-1 2010-12-01 00:03:00 1 497
Con el campo RunDate se incrementando en un minuto (estos registros C.1440 por día) y los períodos siendo 1-48. En bmreports_fpn_curves Tengo un conjunto completo de datos para cada período de tiempo y bmreports_boa_curves contiene los valores que reemplazarán estos valores base.
Por lo general, hay valores de BOA duplicados y una declaración iIF indicada en la extracción sql contenía una regla para elegir uno de los FPN, el valor máximo de BOA o el valor de BOA MIN para cualquier punto en el tiempo . La regla declaró:
1) Si no hay valor de Boa, use el valor FPN
2) Si hay un valor de BOA y es menor que el FPN, encuentre y use el valor Min BOA
3) Si hay un valor de BOA y es mayor que el FPN, encuentra y use el valor MAX BOA
La acceder a la consulta SQL funciona perfectamente y es la siguiente:
SELECT
dbo_BMReports_FPN_Curves.BM_Unit_Name,
dbo_BMReports_FPN_Curves.RunDate,
dbo_BMReports_FPN_Curves.Period,
dbo_BMReports_FPN_Curves.PN_Level,
IIf(IIf(Min([dbo_BMReports_BOA_Curves]![PN_Level]) <[dbo_BMReports_FPN_Curves]![PN_Level],Min([dbo_BMReports_BOA_Curves]! [PN_Level]),Max([dbo_BMReports_BOA_Curves]![PN_Level])) Is Null, [dbo_BMReports_FPN_Curves]![PN_Level],
IIf(Min([dbo_BMReports_BOA_Curves]![PN_Level])<[dbo_BMReports_FPN_Curves]! [PN_Level],Min([dbo_BMReports_BOA_Curves]! [PN_Level]),Max([dbo_BMReports_BOA_Curves]![PN_Level]))) AS BOA
FROM dbo_BMReports_FPN_Curves LEFT JOIN dbo_BMReports_BOA_Curves ON (dbo_BMReports_FPN_Curves.RunDate = dbo_BMReports_BOA_Curves.RunDate) AND (dbo_BMReports_FPN_Curves.BM_Unit_Name = dbo_BMReports_BOA_Curves.BM_Unit_Name)
GROUP BY dbo_BMReports_FPN_Curves.BM_Unit_Name, dbo_BMReports_FPN_Curves.RunDate, dbo_BMReports_FPN_Curves.Period, dbo_BMReports_FPN_Curves.PN_Level
HAVING (((dbo_BMReports_FPN_Curves.BM_Unit_Name)='T_DRAXX-1'));
He vuelto a escribir la mayor parte de la consulta en T-SQL (consultar la misma fuente de datos SQL Server) y tener la unión izquierda, el grupo y tener elementos que todos trabajan, pero me estoy atascando en el caso cuando se reemplaza cuando se reemplaza para el IFF y realmente apreciaría una mano si algunos tienen unos momentos de repuesto.
La consulta de SQL, ya que actualmente significa:
SELECT
BMReports_FPN_Curves.BM_Unit_Name,
BMReports_FPN_Curves.RunDate,
BMReports_FPN_Curves.Period,
AVG(BMReports_FPN_Curves.PN_Level) AS FPN,
CASE
WHEN BMReports_BOA_Curves.PN_Level IS NULL THEN AVG(BMReports_FPN_Curves.PN_Level)
WHEN MIN(BMReports_BOA_Curves.PN_Level) IS < AVG(BMReports_FPN_Curves.PN_Level) THEN MIN(BMReports_BOA_Curves.PN_Level)
ELSE MAX(BMReports_BOA_Curves.PN_Level)
END AS BOA
FROM BMReports_FPN_Curves
LEFT JOIN BMReports_BOA_Curves ON BMReports_FPN_Curves.BM_Unit_Name = BMReports_BOA_Curves.BM_Unit_Name
AND BMReports_FPN_Curves.RunDate = BMReports_BOA_Curves.RunDate
GROUP BY BMReports_FPN_Curves.BM_Unit_Name, BMReports_FPN_Curves.RunDate, BMReports_FPN_Curves.Period
HAVING BMReports_FPN_Curves.BM_Unit_Name = 'T_DRAXX-1'
ORDER BY BMReports_FPN_Curves.BM_Unit_Name, BMReports_FPN_Curves.RunDate, BMReports_FPN_Curves.Period
Solución
SELECT fc.BM_Unit_Name
, fc.RunDate
, fc.Period
, CASE
WHEN AVG(bc.PN_Level) IS NULL THEN AVG(fc.PN_Level) -- No BOA Value, use the FPN Value
WHEN MIN(bc.PN_Level) < AVG(fc.PN_Level) THEN MIN(bc.PN_Level) -- BOA Value is less than the FPN, use the BOA Value
ELSE MAX(bc.PN_Level) -- BOA Value is greater than the FPN, use the BOA Value
END
FROM dbo.BMReports_FPN_Curves fc
LEFT JOIN dbo.BMReports_BOA_Curves bc ON fc.RunDate = bc.RunDate
AND fc.BM_Unit_Name = bc.BM_Unit_Name
WHERE fc.BM_Unit_Name ='T_DRAXX-1'
GROUP BY
fc.BM_Unit_Name
, fc.RunDate
, fc.Period
Otros consejos
Probablemente esté mejor usando un CTE para hacer todos los cálculos agregados y luego hacer su declaración de caso fuera de que
WITH cte
AS (SELECT bmreports_fpn_curves.bm_unit_name,
bmreports_fpn_curves.rundate,
bmreports_fpn_curves.period,
AVG(bmreports_fpn_curves.pn_level) AS fpn,
AVG(bmreports_fpn_curves.pn_level) AS boa,
MIN(bmreports_boa_curves.pn_level) minboa,
MAX(bmreports_fpn_curves.pn_level) maxfpn
FROM bmreports_fpn_curves
LEFT JOIN bmreports_boa_curves
ON bmreports_fpn_curves.bm_unit_name =
bmreports_boa_curves.bm_unit_name
AND bmreports_fpn_curves.rundate =
bmreports_boa_curves.rundate
GROUP BY bmreports_fpn_curves.bm_unit_name,
bmreports_fpn_curves.rundate,
bmreports_fpn_curves.period
HAVING bmreports_fpn_curves.bm_unit_name = 'T_DRAXX-1')
SELECT bm_unit_name,
rundate,
period ,
CASE
WHEN BOA IS NULL THEN FPN
WHEN BOA < FPN THEN MinBoa
WEHN BOA > FPN THEN MaxBoa
ELSE -- BOA = FPN THEN WHAT?
END as BOA
FROM cte
Para DB's que no admiten CTE, también puede usar un selecto dentro de la vista desde (vista en línea).Incidentalmente, el acceso admite esto.
SELECT bm_unit_name,
rundate,
period ,
CASE
WHEN BOA IS NULL THEN FPN
WHEN BOA < FPN THEN MinBoa
WEHN BOA > FPN THEN MaxBoa
ELSE -- BOA = FPN THEN WHAT?
END as BOA
FROM (
SELECT bmreports_fpn_curves.bm_unit_name,
bmreports_fpn_curves.rundate,
bmreports_fpn_curves.period,
AVG(bmreports_fpn_curves.pn_level) AS fpn,
AVG(bmreports_fpn_curves.pn_level) AS boa,
MIN(bmreports_boa_curves.pn_level) minboa,
MAX(bmreports_fpn_curves.pn_level) maxfpn
FROM bmreports_fpn_curves
LEFT JOIN bmreports_boa_curves
ON bmreports_fpn_curves.bm_unit_name =
bmreports_boa_curves.bm_unit_name
AND bmreports_fpn_curves.rundate =
bmreports_boa_curves.rundate
GROUP BY bmreports_fpn_curves.bm_unit_name,
bmreports_fpn_curves.rundate,
bmreports_fpn_curves.period
HAVING bmreports_fpn_curves.bm_unit_name = 'T_DRAXX-1') ) t
¿Has probado una traducción más literal del IIF a caso?Por ejemplo, su cadena IIF se ve algo así:
IIf
(
IIf
(
Min([dbo_BMReports_BOA_Curves]![PN_Level]) < [dbo_BMReports_FPN_Curves]![PN_Level],
Min([dbo_BMReports_BOA_Curves]![PN_Level]),
Max([dbo_BMReports_BOA_Curves]![PN_Level])
) Is Null,
[dbo_BMReports_FPN_Curves]![PN_Level],
IIf
(
Min([dbo_BMReports_BOA_Curves]![PN_Level]) < [dbo_BMReports_FPN_Curves]![PN_Level],
Min([dbo_BMReports_BOA_Curves]![PN_Level]),
Max([dbo_BMReports_BOA_Curves]![PN_Level])
)
) AS BOA
Entonces, una traducción literal sería algo así:
(
case
when
(
case
when Min(BMReports_BOA_Curves.PN_Level) < BMReports_FPN_Curves.PN_Level then
Min(BMReports_BOA_Curves.PN_Level)
else
Max(BMReports_BOA_Curves.PN_Level)
end
) is null then
BMReports_FPN_Curves.PN_Level
else
(
case
when Min(BMReports_BOA_Curves.PN_Level) < BMReports_FPN_Curves.PN_Level then
Min(BMReports_BOA_Curves.PN_Level)
else
Max(BMReports_BOA_Curves.PN_Level)
end
)
end
) as BOA
No tengo acceso a su esquema completo ni a los datos, por lo que no puedo probar la traducción, pero creo que es sin forma correcta.