库/表结构:
CORPORATE/TENANTS
LIB01/INVOICE
LIB02/INVOICE
LIB03/INVOICE
…
LIBxx/INVOICE
CORPORATE/TENANTS
表包含一个库列表,其中存储了有关每个租户的信息。它具有以下结构和数据:
CREATE OR REPLACE TABLE TENANTS (
ID BIGINT GENERATED ALWAYS AS IDENTITY (START WITH 1),
TENANT CHAR(10) NOT NULL,
PRIMARY KEY(ID)
) RCDFMT TENANTSR;
RUNSQLSTM SRCFILE(HILLB/QDDLSRC) SRCMBR(TENANTS) DFTRDBCOL(CORPORATE)
+--+------+
|ID|TENANT|
+--+------+
| 1|LIB01 |
| 2|LIB02 |
|..|......|
|99|LIB99 |
+--+------+
LIBxx/INVOICE
表彼此相同,并具有以下结构:
CREATE OR REPLACE TABLE INVOICE (
ID BIGINT GENERATED ALWAYS AS IDENTITY (START WITH 1),
PAYDAT INTEGER(6,0) NOT NULL,
AMOUNT DECIMAL(15,2) NOT NULL DEFAULT 0,
PRIMARY KEY(ID)
) RCDFMT INVOICER;
+--+------+------+
|ID|PAYDAT|AMOUNT|
+--+------+------+
| 1|180701|100.00|
| 2|180801| 35.00|
|..|......|......|
+--+------+------+
我想生成给定日期所有租户的发票金额列表:
180701 LIB01 100.00
180701 LIB02 140.00
180701 LIB03 74.00
…
从概念上讲,我想这样做(是的,我知道这是无效的SQL):
SELECT PAYDAT, TENANT, AMOUNT
FROM $X.INVOICE
WHERE PAYDAT = 180701;
我想从INVOICE
表中为每个TENANT
提取数据,但是我知道FROM
子句不能像这样动态。我敢肯定这种查询有一个名字,但我不知道它是什么,所以我无法有效地使用搜索引擎来查找所需的东西。
使用RPGLE程序解决这个问题很简单,但我需要一个纯SQL解决方案。
请注意-LIBxx值不能以任何方式进行硬编码。这些值可以随时更改。
答案 0 :(得分:1)
要执行所需的操作,可以在循环中使用带有EXECUTE IMMEDIATE
的存储过程来构建结果集。像这样:
注意:这不是完整的剪切和粘贴解决方案,但是您可以对其进行修改以执行所需的操作。
CREATE OR REPLACE PROCEDURE GETINVOICEAMOUNTS ( )
DYNAMIC RESULT SETS 1
LANGUAGE SQL
NOT DETERMINISTIC
MODIFIES SQL DATA
CALLED ON NULL INPUT
SET OPTION COMMIT = *NONE
BEGIN
DECLARE STMT VARCHAR(1024);
DECLARE RECORD_FOUND INTEGER DEFAULT 1;
DECLARE LIBRARY CHAR(10);
DECLARE C1 CURSOR FOR
SELECT TENANT FROM CORPORATE/TENANT;
DECLARE C2 CURSOR WITH RETURN FOR
SELECT * FROM SESSION.TMP ;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET RECORD_FOUND = 0;
DECLARE GLOBAL TEMPORARY TABLE TMP
(PAYDAT INTEGER(6,0),
TENANT CHAR(10),
AMOUNT DECIMAL(15,2))
WITH REPLACE;
OPEN C1;
LOOP
FETCH C1 INTO LIBRARY;
IF RECORD_FOUND = 0;
LEAVE LOOP;
END IF;
SET STMT = 'INSERT INTO SESSION.TMP SELECT PAYDAT, LIBRARY, AMOUNT FROM ' || RTRIM(LIBRARY) || '.INVOICE WHERE PAYDAT = 180701';
EXECUTE IMMEDIATE STMT
END LOOP;
CLOSE C1;
OPEN C2;
END;
我给了你比计划更多的东西。但是,您始终需要进行的一项特定修改是参数化您要检索的日期。
它是这样工作的:
名为TMP
的全局临时表用于收集要在结果集中返回的记录。收集完所有记录后,将在TMP
上打开光标,然后过程结束。这将导致在TMP中收集的值作为结果集返回。
要收集值,请读取CORPORATE/TENANT
文件,并将列TENANT
检索到变量LIBRARY
中。对于每个记录,都会建立一个将LIBRARY
连接到INSERT
语句中的语句。执行该语句,将记录加载到TMP
中。我使用EXECUTE IMMEDIATE
是因为我不能使用参数标记来替换INSERT
语句中的表引用,所以准备好的语句只是多余的工作。
答案 1 :(得分:0)
您可以使用UNION ALL
:
SELECT sub.PAYDAT, t.TENANT, sub.AMOUNT
FROM (SELECT * FROM LIB01.INVOICE
UNION ALL
SELECT * FROM LIB02/INVOICE
...
SELECT * FROM LIB0n/INVOICE) sub
JOIN TENANTS t
ON sub.id = t.id
WHERE SUB.PAYDAT = 180701;
这是一个SELECT * FROM sales + @yymm模板。
编辑:
更安全的方法是创建视图:
CREATE VIEW combined_invoice
AS
SELECT * FROM LIB01.INVOICE
UNION ALL
SELECT * FROM LIB02/INVOICE
...
SELECT * FROM LIB0n/INVOICE;
并查询:
SELECT sub.PAYDAT, t.TENANT, sub.AMOUNT
FROM combined_invoice sub
JOIN TENANTS t
ON sub.id = t.id
WHERE SUB.PAYDAT = 180701;
当然,添加/删除表后应该更改视图。