工作 Access SQL 查询的 T-SQL 迁移,在编写 IIF 的 CASE 替换时存在问题
我有两个表 BMReports_FPN_Curves 和 BMReports_BOA_Curves,每个表都包含名称、日期时间、期间和值,例如:
BM_UNIT_NAME RunDate Period FPN (or BOA)
T_DRAXX-1 2010-12-01 00:03:00 1 497
RunDate 字段递增一分钟(此 c.1440 条记录)每天),周期为 1-48。在 BMReports_FPN_Curves 中,我有每个时间段的完整数据集,并且 BMReports_BOA_Curves 包含将替换这些基值的值。
通常存在重复的 BOA 值,并且 Access SQL 语句中的嵌套 IIF 语句包含一条规则,用于选择任意时间点的 FPN、最大 BOA 值或最小 BOA 值之一。规则规定:
1)如果没有BOA值,则使用FPN值
2) 如果存在BOA值且小于FPN,则查找并使用Min BOA值
3)如果有一个BOA值并且它大于FPN,找到并使用最大BOA值
Access SQL查询工作完美,如下所示:
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'));
我已经重写了大部分T-SQL 中的查询(查询相同的 SQL Server 数据源)并且 LEFT JOIN、GROUP BY 和 HAVING 元素都正常工作,但我陷入了 CASE WHEN 替换 IFF 的困境,如果有人有帮助,我将非常感激稍等片刻。
目前的 SQL 查询:
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
I have two tables BMReports_FPN_Curves and BMReports_BOA_Curves each consisting of a Name, Datetime, Period and Value, for example:
BM_UNIT_NAME RunDate Period FPN (or BOA)
T_DRAXX-1 2010-12-01 00:03:00 1 497
With the RunDate field incrementing by one minute (this c.1440 records per day) and the Periods being 1-48. In BMReports_FPN_Curves I have a complete data set for each time period and BMReports_BOA_Curves contains the values that will replace these base values.
There are usually duplicate BOA values and a nested IIF statement in the Access SQL statement contained a rule to pick one of either the FPN, the max BOA value or Min BOA value for any point in time. The rule stated:
1) If there is no BOA value, use the FPN value
2) If there is a BOA value and it is less than the FPN, find and use the Min BOA value
3) If there is a BOA value and it is greater than the FPN, find and use the Max BOA value
The Access SQL query works perfectly and is as follows:
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'));
I've re-written the bulk of the query in T-SQL (querying the same SQL Server data source) and have the LEFT JOIN, GROUP BY and HAVING elements all working but I am getting stuck on the CASE WHEN replacement for the IFF and would really appreciate a hand if some has a few moments spare.
The SQL Query as it currently stands:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可能最好使用 CTE 进行所有聚合计算,然后执行 case 语句。
对于不支持 CTE 的数据库,您还可以在 from (内联视图)中使用选择。顺便说一下,Access 支持这一点。
You're probably better off using a CTE to do all the aggregate calculations and then doing your case statement off that
For DB's that don't support CTEs you can also use a select inside the from (inline view). Incidentally Access supports this.
您是否尝试过将 IIF 更直译为 CASE?例如,您的 IIF 链看起来像这样:
因此直译会是这样的:
我无法访问您的完整架构或数据,因此我无法测试翻译,但我相信它在语法上是正确的。
Have you tried a more literal translation of the IIF to CASE? For example, your IIF chain looks something like this:
So a literal translation would be something like this:
I don't have access to your full schema nor data so I cannot test the translation, but I believe it is syntactically correct.