SQL 语句之间的区别
Difference between SQL statements
我遇到了 SQLRPGLE 程序的两个版本,并看到代码发生了如下变化:
之前:
Exec Sql SELECT 'N'
INTO :APRFLG
FROM LG751F T1
INNER JOIN LG752F T2
ON T1.ISBOLN = T2.IDBOLN AND
T1.ISITNO = T2.IDMDNO
WHERE T2.IDVIN = :M_VIN AND
T1.ISAPRV <> 'Y';
之后:
Exec Sql SELECT case
when T1.ISAPRV <> 'Y' then 'N'
else T1.ISAPRV
end as APRFLG
INTO :APRFLG
FROM LG751F T1
join LG752F T2
ON T1.ISBOLN = T2.IDBOLN AND
T1.ISITNO = T2.IDMDNO
WHERE T2.IDVIN = :M_VIN AND
T1.ISAPRV <> 'Y'
group by T1.ISAPRV;
如果您发现这些代码的工作方式有何不同,能否告诉我?第二个 SQL 有一个组,应该是一个避免 -811 SQLCod 错误的修复。除此之外,大家有发现什么不同吗?
除了添加分组依据之外,我没有发现任何引人注目的区别,这将具有抑制可能已输出的任何重复行的效果。
看起来开发人员希望查询能够将其输出更改为有时是 Y 有时是 N,但忘记删除必须强制大小写始终为真的 WHERE 子句,因此它总是输出 N。 这种模式通常出现在原始报告包含一些规范,如 "don't include managers in the employee Sakarya report" 然后更改为 "actually we want to know if the employee is a manager or not" 时。 "where employee not equal manager" 变成了 "case when employee is manager then... else.." 但 where 子句需要删除才能生效
inner 关键字已从 join 语句中消失,但总体而言这也应该是一个非操作
它们都是 IMO 编码不佳的例子。
对 "remove duplicates" 的要求通常表明语句设计不当 and/or 数据库设计不当。
您似乎在进行存在性检查,在这种情况下,您应该使用 EXISTS
谓词。
select 'N' into :APRFLG
from sysibm.sysdummy1
where exists (select 1
FROM LG751F T1
INNER JOIN LG752F T2
ON T1.ISBOLN = T2.IDBOLN
AND T1.ISITNO = T2.IDMDNO
WHERE
T2.IDVIN = :M_VIN
AND T1.ISAPRV <> 'Y');
就原来的两个语句而言,除了分组依据之外,唯一真正的区别是将列从 JOIN
子句移动到 WHERE
子句。但是,Db2 for i 中的查询引擎将等效地重写这两个语句并得出相同的计划;因为使用了内部连接。
EDIT : 正如 Mark 指出的那样,JOIN
和 WHERE
在两个 OP 的陈述中是相同的。但我会将上面的声明保留为仅供参考。
另一种选择是像这样使用 fetch first row only
:
Exec Sql
SELECT 'N'
INTO :APRFLG
FROM LG751F T1
JOIN LG752F T2
ON T1.ISBOLN = T2.IDBOLN AND
T1.ISITNO = T2.IDMDNO
WHERE T2.IDVIN = :M_VIN AND
T1.ISAPRV <> 'Y'
fetch first row only;
这更明显地表明您只需要一行而不是尝试使用分组,这需要时髦的 do nothing CASE
语句。但我确实喜欢 Charles 提供的 EXISTS
方法,因为这是真正的目标,并且 exists 使它 crystal 清晰。
如果您的领导坚持 GROUP BY
,您也可以 GROUP BY 'N'
并且仍然省略 CASE
声明。
我遇到了 SQLRPGLE 程序的两个版本,并看到代码发生了如下变化:
之前:
Exec Sql SELECT 'N'
INTO :APRFLG
FROM LG751F T1
INNER JOIN LG752F T2
ON T1.ISBOLN = T2.IDBOLN AND
T1.ISITNO = T2.IDMDNO
WHERE T2.IDVIN = :M_VIN AND
T1.ISAPRV <> 'Y';
之后:
Exec Sql SELECT case
when T1.ISAPRV <> 'Y' then 'N'
else T1.ISAPRV
end as APRFLG
INTO :APRFLG
FROM LG751F T1
join LG752F T2
ON T1.ISBOLN = T2.IDBOLN AND
T1.ISITNO = T2.IDMDNO
WHERE T2.IDVIN = :M_VIN AND
T1.ISAPRV <> 'Y'
group by T1.ISAPRV;
如果您发现这些代码的工作方式有何不同,能否告诉我?第二个 SQL 有一个组,应该是一个避免 -811 SQLCod 错误的修复。除此之外,大家有发现什么不同吗?
除了添加分组依据之外,我没有发现任何引人注目的区别,这将具有抑制可能已输出的任何重复行的效果。
看起来开发人员希望查询能够将其输出更改为有时是 Y 有时是 N,但忘记删除必须强制大小写始终为真的 WHERE 子句,因此它总是输出 N。 这种模式通常出现在原始报告包含一些规范,如 "don't include managers in the employee Sakarya report" 然后更改为 "actually we want to know if the employee is a manager or not" 时。 "where employee not equal manager" 变成了 "case when employee is manager then... else.." 但 where 子句需要删除才能生效
inner 关键字已从 join 语句中消失,但总体而言这也应该是一个非操作
它们都是 IMO 编码不佳的例子。
对 "remove duplicates" 的要求通常表明语句设计不当 and/or 数据库设计不当。
您似乎在进行存在性检查,在这种情况下,您应该使用 EXISTS
谓词。
select 'N' into :APRFLG
from sysibm.sysdummy1
where exists (select 1
FROM LG751F T1
INNER JOIN LG752F T2
ON T1.ISBOLN = T2.IDBOLN
AND T1.ISITNO = T2.IDMDNO
WHERE
T2.IDVIN = :M_VIN
AND T1.ISAPRV <> 'Y');
就原来的两个语句而言,除了分组依据之外,唯一真正的区别是将列从 JOIN
子句移动到 WHERE
子句。但是,Db2 for i 中的查询引擎将等效地重写这两个语句并得出相同的计划;因为使用了内部连接。
EDIT : 正如 Mark 指出的那样,JOIN
和 WHERE
在两个 OP 的陈述中是相同的。但我会将上面的声明保留为仅供参考。
另一种选择是像这样使用 fetch first row only
:
Exec Sql
SELECT 'N'
INTO :APRFLG
FROM LG751F T1
JOIN LG752F T2
ON T1.ISBOLN = T2.IDBOLN AND
T1.ISITNO = T2.IDMDNO
WHERE T2.IDVIN = :M_VIN AND
T1.ISAPRV <> 'Y'
fetch first row only;
这更明显地表明您只需要一行而不是尝试使用分组,这需要时髦的 do nothing CASE
语句。但我确实喜欢 Charles 提供的 EXISTS
方法,因为这是真正的目标,并且 exists 使它 crystal 清晰。
如果您的领导坚持 GROUP BY
,您也可以 GROUP BY 'N'
并且仍然省略 CASE
声明。