【问题标题】:SQL, Firebird, Dynamic Union based on other TableSQL、Firebird、基于其他表的动态联合
【发布时间】:2014-10-11 12:38:35
【问题描述】:

我需要你的帮助。我需要构建一个动态联合 SQL 语句。 (或存储过程)

TableA1 中存储了我的 SQL 参数的值。 例如:

ID | Name
1 | 16
2 | 23
3 | 30

TableB1 中存储了所有其他值。但我需要为 TableA1 中的每一行联合

例如:

Select b.* from TableB1 b
join TableA1 a on a.ID = b.ID
where b.ID = 1
union
Select b.* from TableB1
join TableA1 a on a.ID = b.ID
where b.ID = 2

因为 TableA1 是动态的,所以无法制作静态 union-sql。请帮我。我可以这样做吗: cte WITH ?

最好的问候 射频

第二种解释: 我会尽量让我的解释更容易理解。对不起我的第一个问题。我发现它不正确。

由于 TableB1 的表格设计,我需要一个动态联合(或其他东西)。以水平方式存储每个月/年的值。

示例TableB1

日期 | xxxx | ID1 | ID2 | ID3 |身份证4 ... 2014-07 | n | 20 | 30 | 40 | 2014-08 | n | 40 | 50 | 70 |

输出应如下所示:

TableB1.日期 |表A1.ID |表 A1.名称 |表 B1.ID x | 2014-07 | 1 | 16 | 20 2014-08 | 1 | 16 | 40 2014-07 | 2 | 23 | 30 2014-08 | 2 | 23 | 50 2014-07 | 3 | 30 | 40 2014-08 | 3 | 30 | 70

我想我会将 sql 放入存储过程中,因为对于每个联合,我必须更改 SQL 语法以获取正确的列。

也许我必须先创建一个非透视存储过程。你知道我如何在 Firebird 中制作这个吗?

【问题讨论】:

  • 你能提供一些示例预期输出吗?为什么你不能这样做:Select b.* from TableB1 b join TableA1 a on a.ID = b.ID
  • 阅读您的查询和您的问题,我看到的是您正在为联合选择 TableB1 的内容,而不是对 TableA1 做任何事情。另请注意:为什么不避免联合并使用IN predicate
  • 这是 Firebird 还是 SQL-Server?为什么要两个标签?
  • @Frazz:因为该软件可以通过安装 Firebird 或 MSSQL 数据库来使用。两个数据库都支持-
  • TableB1 的结构显然是问题所在。您想使用 TableA1 的 ID 从 TableB1 中选择一列。您不能将 TableB1 重组为每个日期和 ID 一行,外加一列值吗?这将是查询和维护的最佳解决方案。否则,您将需要复杂的 CASE 语句或存储过程。但是,当您在 TableA1(以及 TableB1 中的新列)中添加新 ID 时,两者都不够灵活以适应自身。

标签: sql sql-server union firebird unpivot


【解决方案1】:

我不确定 TableB1 中的字段 xxxx 代表什么,但我假设您在 TableB1 中没有 ID 字段,并且对于 TableA1 中的每个 ID,您需要 TableB1 中的相应 IDx 字段。我还假设您的 ID 字段是数字并且名称是数字。 这是执行块中的示例代码,但可以很容易地放入存储过程中。执行块的原因是,如果通过 ADO 执行,它会变得灵活。

我扩展了 Frazz 所说的重组 TableB1 的想法。

您将需要以下临时表

CREATE GLOBAL TEMPORARY TABLE GTT_TEMP (
    DT   VARCHAR(10),
    ID   INTEGER,
    VAL  INTEGER
) ON COMMIT DELETE ROWS;

这里是 SQL

EXECUTE BLOCK
returns (TableB1_DATE VARCHAR(10),
         TableA1_ID INTEGER,
         tableA1_Name INTEGER,
         tableB1_ID INTEGER )
as
declare variable sql varchar(1000);
declare variable id integer;
begin

    for
    Select TABLEA1.ID FROM TABLEA1
    INTO :id
    do
    begin
       sql = 'INSERT INTO GTT_TEMP ( DT, ID, VAL ) SELECT tableb1."DATE", '||:id||', ID'||:id||' from tableb1 WHERE tableb1.ID'||:id||' > 0' ;
       EXECUTE Statement :sql;
    end

    FOR 
    Select GTT_TEMP.DT, GTT_TEMP.ID, tablea1.NAME, GTT_TEMP.VAL from GTT_TEMP, TABLEA1 WHERE tablea1.ID = gtt_temp.ID
    INTO :TableB1_DATE,
         :TableA1_ID,
         :TableA1_NAME,
         :TableB1_ID
     DO
     BEGIN
        suspend;
     END

END

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    • 2019-05-20
    • 1970-01-01
    相关资源
    最近更新 更多