SQL、Firebird、基于其他表的动态联合

SQL、Firebird、基于其他表的动态联合,sql,sql-server,union,firebird,unpivot,Sql,Sql Server,Union,Firebird,Unpivot,我需要你的帮助。我需要构建一个动态联合SQL语句。 (或存储过程) 在表A1中有为我的SQL参数存储的值。 例如: ID | Name 1 | 16 2 | 23 3 | 30 在表B1中存储了所有其他值。但表1中的每一行我都需要一个工会 例如: 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 =

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

表A1中有为我的SQL参数存储的值。 例如:

ID | Name
1 | 16
2 | 23
3 | 30
表B1中存储了所有其他值。但表1中的每一行我都需要一个工会

例如:

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是动态的,所以不可能生成静态联合sql。请帮帮我。我可以用:cte with做这个吗

致意 射频

第二种解释: 我会尽量使我的解释更容易理解。对不起,我的第一个问题。我看这是不对的

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

示例表B1

date | xxxx | ID1 | ID2 | ID3 | ID4 ... 2014-07 | n | 20 | 30 | 40 | 2014-08 | n | 40 | 50 | 70 | 日期| xxxx | ID1 | ID2 | ID3 | ID4。。。 2014-07 | n | 20 | 30 | 40| 2014-08 | n | 40 | 50 | 70| 输出应如下所示:

TableB1.date | TableA1.ID | TableA1.Name | TableB1.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 表B1.date |表A1.ID |表A1.Name |表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语法以获得正确的列


也许我必须先做一个unpivot存储过程。您知道我如何在Firebird中实现这一点吗?

我不确定表B1中的字段xxxx代表什么,但我假设您在表B1中没有ID字段,并且对于表A1中的每个ID,您需要表B1中相应的IDx字段。我还假设您的ID字段是数字,名称是数字。 下面是EXECUTE块内的示例代码,但可以轻松地放入存储过程中。使用execute块的原因是,例如,如果通过ADO执行,它会变得灵活

我进一步阐述了Frazz所说的重组表格B1的想法

您将需要以下临时表

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

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