iSeries SQL:选择记录以创建 table 时不允许使用当前日期
iSeries SQL: current date not allowed when selecting records to create a table
我需要创建一个具体化查询 table,其中的记录具有通过子查询在第二个 table 上检索到的属性,以便获取该属性的最新值。
这个问题与此处讨论的问题非常相似:Retrieving the last record in each group 除了以下内容:
- 内部子查询必须比较第二个table的有效日期
current_date(或 CURDATE)不是主 table
的另一个日期字段
- 结果用于创建新的具体化查询table
在这些假设下,SQL 异常结束并给出 SQ20058 错误,可以通过两种方式消除:
- 使用特定日期而不是 current_date,这使得声明对我的目的毫无用处
添加
disable query optimization
到语句末尾的当前设置
data initially deferred
refresh deferred
maintained by user
这又会禁用 iSeries V7R1 操作系统进行的查询优化。
为了解决这个问题,我尝试创建一个视图,其中包含内部子查询提取的所有记录,然后发出一个 create table 语句加入视图,以避免执行子查询,但再次具体化查询 table 无法找到包含对当前日期的引用的视图。
您知道如何在创建 table 时将记录与当前日期进行比较吗?
我错过了什么?
谢谢
示例:
1) 给定销售额 table 定义为:
create table sales (
item_id decimal(3, 0),
sale_date date,
sale_qty decimal(7, 2)
)
内容如下:
ITEM_ID SALE_DATE SALE_QTY
1 2016-01-10 10,00
1 2016-02-10 10,00
1 2016-03-10 10,00
2 2016-01-10 5,00
2 2016-02-10 5,00
2 2016-03-10 5,00
2) 和部门 table 定义为:
create table depts (
item_id decimal(3, 0),
dept_from_date date,
dept_id character(3)
)
内容如下:
ITEM_ID DEPT_FROM_DATE DEPT_ID
1 2016-01-01 AAA
1 2016-03-01 BBB
2 2016-01-01 BBB
2 2016-02-01 CCC
2 2016-05-01 DDD
2 2016-12-01 EEE
3) 这是预期的结果:
select s.item_id, s.sale_date, s.sale_qty, d.dept_id
from sales s
left join depts d on d.item_id=s.item_id
and d.dept_from_date = (
select max(dept_from_date)
from depts x
where x.item_id = d.item_id and dept_from_date <= current_date)
ITEM_ID SALE_DATE SALE_QTY DEPT_ID
1 2016-01-10 10,00 BBB
1 2016-02-10 10,00 BBB
1 2016-03-10 10,00 BBB
2 2016-01-10 5,00 DDD
2 2016-02-10 5,00 DDD
2 2016-03-10 5,00 DDD
出于 BI 目的,部门 ID 被扁平化为其最新值
4) 当前面的 select 语句嵌入到创建 table 语句中时,如下所示:
create table sales2 as (
select s.item_id, s.sale_date, s.sale_qty, d.dept_id
from sales s
left join depts d on d.item_id=s.item_id
and d.dept_from_date = (
select max(dept_from_date)
from depts x
where x.item_id = d.item_id and dept_from_date <= current_date))
data initially deferred
refresh deferred
maintained by user
它returns SQ20058 错误。
编辑
您只需将“DISABLE QUERY OPTIMIZATION”参数添加到 MQT 的末尾即可。从文档来看,它所做的是:
Specifies that the materialized query table cannot be used for query
optimization. The table can still be queried directly.
因此,除非您希望系统维护 MQT 并且查询优化器将 MQT 用于原始 table 上的 select 语句,否则您可以只指定 DISABLE QUERY OPTIMIZATION 参数。
原答案
在“数据最初延迟立即刷新”参数的情况下,我把它留在这里。指定用于系统维护的 MQT。
看到没有“DISABLE QUERY OPTIMIZATION”参数的 MQT 不允许您使用特殊寄存器:
Subselect for materialized query table SALES2 not valid for reason code 8.
8 -- Refers to a special register or global variable.
在 MQT 的定义中没有使用 CURRENT_DATE 的任何正确方法。因此,我个人建议您最好根据 select 语句创建一个视图。
话虽这么说,这里有一个黑客(或更像是电锯大屠杀)方法,你可以这样做:
创建一个 table 来存储当前日期:
CREATE TABLE cur_dat (cur_dat DATE)
INSERT INTO cur_dat VALUES(CURRENT DATE)
然后创建一个作业计划条目,每晚 table 午夜更新此条目:
QSYS/ADDJOBSCDE JOB(UPD_CURDAT)
CMD(RUNSQL SQL('UPDATE cur_dat SET cur_dat = CURRENT DATE') COMMIT(*NONE))
FRQ(*WEEKLY)
SCDDATE(*NONE)
SCDDAY(*ALL)
SCDTIME('00:00:00')
最后将您的 MQT 定义更改为:
CREATE TABLE sales2 AS (
SELECT s.item_id, s.sale_date, s.sale_qty, d.dept_id
FROM sales s
LEFT JOIN depts d ON d.item_id = s.item_id
AND d.dept_from_date = (SELECT MAX(x.dept_from_date)
FROM depts x, cur_dat y
WHERE x.item_id = d.item_id
AND x.dept_from_date <= y.cur_dat)
)
data initially deferred refresh immediate
我需要创建一个具体化查询 table,其中的记录具有通过子查询在第二个 table 上检索到的属性,以便获取该属性的最新值。 这个问题与此处讨论的问题非常相似:Retrieving the last record in each group 除了以下内容:
- 内部子查询必须比较第二个table的有效日期 current_date(或 CURDATE)不是主 table 的另一个日期字段
- 结果用于创建新的具体化查询table
在这些假设下,SQL 异常结束并给出 SQ20058 错误,可以通过两种方式消除:
- 使用特定日期而不是 current_date,这使得声明对我的目的毫无用处
添加
disable query optimization
到语句末尾的当前设置
data initially deferred refresh deferred maintained by user
这又会禁用 iSeries V7R1 操作系统进行的查询优化。
为了解决这个问题,我尝试创建一个视图,其中包含内部子查询提取的所有记录,然后发出一个 create table 语句加入视图,以避免执行子查询,但再次具体化查询 table 无法找到包含对当前日期的引用的视图。
您知道如何在创建 table 时将记录与当前日期进行比较吗? 我错过了什么?
谢谢
示例: 1) 给定销售额 table 定义为:
create table sales (
item_id decimal(3, 0),
sale_date date,
sale_qty decimal(7, 2)
)
内容如下:
ITEM_ID SALE_DATE SALE_QTY
1 2016-01-10 10,00
1 2016-02-10 10,00
1 2016-03-10 10,00
2 2016-01-10 5,00
2 2016-02-10 5,00
2 2016-03-10 5,00
2) 和部门 table 定义为:
create table depts (
item_id decimal(3, 0),
dept_from_date date,
dept_id character(3)
)
内容如下:
ITEM_ID DEPT_FROM_DATE DEPT_ID
1 2016-01-01 AAA
1 2016-03-01 BBB
2 2016-01-01 BBB
2 2016-02-01 CCC
2 2016-05-01 DDD
2 2016-12-01 EEE
3) 这是预期的结果:
select s.item_id, s.sale_date, s.sale_qty, d.dept_id
from sales s
left join depts d on d.item_id=s.item_id
and d.dept_from_date = (
select max(dept_from_date)
from depts x
where x.item_id = d.item_id and dept_from_date <= current_date)
ITEM_ID SALE_DATE SALE_QTY DEPT_ID
1 2016-01-10 10,00 BBB
1 2016-02-10 10,00 BBB
1 2016-03-10 10,00 BBB
2 2016-01-10 5,00 DDD
2 2016-02-10 5,00 DDD
2 2016-03-10 5,00 DDD
出于 BI 目的,部门 ID 被扁平化为其最新值
4) 当前面的 select 语句嵌入到创建 table 语句中时,如下所示:
create table sales2 as (
select s.item_id, s.sale_date, s.sale_qty, d.dept_id
from sales s
left join depts d on d.item_id=s.item_id
and d.dept_from_date = (
select max(dept_from_date)
from depts x
where x.item_id = d.item_id and dept_from_date <= current_date))
data initially deferred
refresh deferred
maintained by user
它returns SQ20058 错误。
编辑
您只需将“DISABLE QUERY OPTIMIZATION”参数添加到 MQT 的末尾即可。从文档来看,它所做的是:
Specifies that the materialized query table cannot be used for query optimization. The table can still be queried directly.
因此,除非您希望系统维护 MQT 并且查询优化器将 MQT 用于原始 table 上的 select 语句,否则您可以只指定 DISABLE QUERY OPTIMIZATION 参数。
原答案
在“数据最初延迟立即刷新”参数的情况下,我把它留在这里。指定用于系统维护的 MQT。
看到没有“DISABLE QUERY OPTIMIZATION”参数的 MQT 不允许您使用特殊寄存器:
Subselect for materialized query table SALES2 not valid for reason code 8.
8 -- Refers to a special register or global variable.
在 MQT 的定义中没有使用 CURRENT_DATE 的任何正确方法。因此,我个人建议您最好根据 select 语句创建一个视图。
话虽这么说,这里有一个黑客(或更像是电锯大屠杀)方法,你可以这样做:
创建一个 table 来存储当前日期:
CREATE TABLE cur_dat (cur_dat DATE)
INSERT INTO cur_dat VALUES(CURRENT DATE)
然后创建一个作业计划条目,每晚 table 午夜更新此条目:
QSYS/ADDJOBSCDE JOB(UPD_CURDAT)
CMD(RUNSQL SQL('UPDATE cur_dat SET cur_dat = CURRENT DATE') COMMIT(*NONE))
FRQ(*WEEKLY)
SCDDATE(*NONE)
SCDDAY(*ALL)
SCDTIME('00:00:00')
最后将您的 MQT 定义更改为:
CREATE TABLE sales2 AS (
SELECT s.item_id, s.sale_date, s.sale_qty, d.dept_id
FROM sales s
LEFT JOIN depts d ON d.item_id = s.item_id
AND d.dept_from_date = (SELECT MAX(x.dept_from_date)
FROM depts x, cur_dat y
WHERE x.item_id = d.item_id
AND x.dept_from_date <= y.cur_dat)
)
data initially deferred refresh immediate