在DB2 SQL中,是否可以在SELECT语句中设置一个变量以多次使用..?

时间:2018-02-16 14:02:37

标签: db2 ibm-midrange db2-400

在DB2 SQL中,是否可以SET一个带有SELECT语句中返回字段内容的变量,可以在同一个{{{1}中进一步使用计算字段和条件。 1}}陈述?

目的是缩小和简化代码,方法是在开始时进行一次计算并稍后多次使用...包括SELECTHAVING和{{1} }。

说实话,我不确定在任何版本的SQL中都可以这样做,更不用说DB2了。

这是在带有DB2 SQL v6的IBM iSeries 8202上,不幸的是,目前还没有升级的候选者。这是一个非常古老的&凌乱的数据库,我无法控制。我必须经常包括"清理功能"在我的SQL中。

要澄清问题,请注意以下伪代码。实际工作代码如下所示。

WHERE

下面是我实际工作的SQL。在2017或2016年调整后,它可以返回> 10K行,具体取决于销售人员。完整的表格具有> 22M行。

我希望用变量代替ORDER BY函数。这不是唯一的例子。如果我可以使它工作,我有许多其他查询可以从该技术中受益。

DECLARE smnum INTEGER --Not sure if this is correct.
SELECT
-- This is where I'm not sure what to do.
SET CAST((CASE WHEN %smnum%='' THEN '0' ELSE %smnum% END) AS INTEGER) INTO smnum, 
%smnum% AS sm,
invdat, 
invno, 
daqty, 
dapric,
dacost,  
(dapric-dacost)*daqty AS profit
FROM 
saleshistory
WHERE 
%smNum% = 30
ORDER BY
%smnum%

3 个答案:

答案 0 :(得分:2)

只需使用子查询或CTE。我无法弄清楚你想要的实际逻辑,但结构如下:

select . . .
from (select d.*, 
             (CASE . . . END) as calc_field
      from VIPDTAB.DAILYV d
     ) d

不需要变量声明。

答案 1 :(得分:1)

以下是您使用Gordon建议的子查询的SQL的样子:

SELECT

DASM,
DAIDAT,
DAINV# AS DAINV,
DALIN# AS DALIN,
CAST(DAITEM AS INTEGER) AS DAITEM,
TRIM(DABSW) AS DABSW,
TRIM(DAPCLS) AS DAPCLS,
DAQTY,
DAPRIC,
DAICOS,
DADPAL,
(DAPRIC-DAICOS+DADPAL)*DAQTY AS PROFIT

FROM

(SELECT 
   D.*, 
   CAST((CASE WHEN D.DASM#='' THEN '0' ELSE D.DASM# END) AS INTEGER) AS DASM
   FROM VIPDTAB.DAILYV D
) D

WHERE

DASM=30 AND
TRIM(DABSW)='B' AND
DAIDAT BETWEEN (YEAR(CURDATE())*10000) AND (((YEAR(CURDATE())+1)*10000)-1) AND 
CAST(DACOMP AS INTEGER)=1

ORDER BY

DASM,
DAIDAT,
DAINV#,
DALIN#

请注意,我删除了很多trim()函数,您可能会删除其余的函数。 IBM解析Varchar与Char比较的方式是忽略尾随空白。因此trim(anything) = ''anything = ''相同。自cast(' 123 ' as integer) = 123以来,我已经从强制转换函数中移除了修剪。此外,只要trim(dabsw) = 'B'dabsw = 'B'中的第一个字符,'B'就与dabsw相同。因此,如果你所关心的只是尾随空白,你甚至可以删除那个修剪。

以下是一些基于评论的附加说明。以上段落并不是在谈论自动修剪。固定长度字段将始终作为固定长度字段返回,尾随空白将保留。但是在比较和表达中,尾随空白不重要,甚至是障碍,它们都会被忽略。在尾随空白很重要的表达式中,如连接,不会忽略尾随空格。另一件事,trim()删除了前导空格和尾随空格。如果您使用trim()将固定长度字符字段读入Varchar,则rtrim()可能是更好的选择,因为它只会删除尾随空白。

另外,我没有通过你的字段来确保我得到你需要的一切,我只是在子查询中使用了*。为了提高性能,最好只返回您需要的字段。因此,如果将D.*替换为实际字段列表,则可以删除子查询的from子句中的相关名称。但是,子查询本身仍然需要一个关联子句。

我的验证是使用IBM i v7.1完成的。

答案 2 :(得分:0)

您可以在视图中封装case语句。我甚至在那里有花哨的利润计划供您按利润订购。现在最大的问题是计算列视图上的CCSID,但这是另一个问题。

create or replace view VIPDTAB.DAILYVQ  as 

SELECT
CAST((CASE WHEN TRIM(DASM#)='' THEN '0' ELSE TRIM(DASM#) END) AS INTEGER) AS DASM,
DAIDAT,
DAINV# AS DAINV,
DALIN# AS DALIN,
CAST(TRIM(DAITEM) AS INTEGER) AS DAITEM,
TRIM(DABSW) AS DABSW,
TRIM(DAPCLS) AS DAPCLS,
DAQTY,
DAPRIC,
DAICOS,
DADPAL,
(DAPRIC-DAICOS+DADPAL)*DAQTY AS PROFIT

FROM

VIPDTAB.DAILYV

现在你可以

select dasm, count(*) from vipdtab.dailyvq where dasm = 0 group by dasm order by dasm

select * from vipdtab.dailyvq order by profit desc