1

如何正确显示两个不相关的选择查询,在过程中没有相互字段?

Table1
        Number
          1
          2
          3
          4
          5

Table2
        Letter
          a

当我尝试使用此程序呼叫他们时,

CREATE PROCEDURE SAMPLE
RETURNS(
  Number SMALLINT,
  Letter Varchar)
AS
BEGIN
  FOR
    SELECT
      A.Number,
      B.Letter
    FROM Table1 A, Table2 B
    INTO
      :Number,
      :Letter
  DO
    BEGIN
      SUSPEND;
    END
END;

我得到这个结果

Number Letter
  1      a
  2      a
  3      a
  4      a
  5      a

这是我想要的结果

   Number Letter
      1      a
      2      
      3      
      4      
      5      
4

1 回答 1

0

假设您想要“压缩”一个不相关集的结果集,您应该为任一表中的每一行分配一个行号(使用 Firebird 3's row_number()),然后加入该行(使用外连接,所以哪个有更多行)。

这将导致查询如下所示:

select a.number, b.letter
from (select row_number() over() as t1nr, number from table1) a
full outer join (select row_number() over() as t2nr, letter from table2) b
    on a.t1nr = b.t2nr

请注意,根据您的需要,您可能需要为 指定明确的顺序row_number(),例如row_number() over(order by number)row_number() over(order by letter)

或者,您可以使用CURSORFirebird 存储过程中的支持并手动控制迭代,但这会变得非常混乱且难以遵循。

您可以执行如下所示的操作(我使用的是 Firebird 3,但将这些布尔值替换为 smallint 并使用 1 和 0 应该适用于 Firebird 2.0 - 2.5)。为了便于阅读,我使用了表名numbersletters不是table1andtable2

execute block returns (number integer, letter char(1))
as
  declare cur_numbers cursor for (select number from numbers);
  declare cur_letters cursor for (select letter from letters);
  declare all_numbers_fetched boolean = false;
  declare all_letters_fetched boolean = false;
begin
  open cur_numbers;
  open cur_letters;
  while (true) do
  begin
    
    if (not all_numbers_fetched) then
    begin
      -- fetch a single row from numbers
      fetch cur_numbers into :number;
      if (row_count = 0) then
      begin
        -- all numbers fetched
        close cur_numbers;
        all_numbers_fetched = true;
        number = null;
      end
    end
    
    if (not all_letters_fetched) then
    begin
      -- fetch a single row from letters
      fetch cur_letters into :letter;
      if (row_count = 0) then
      begin
        -- all letters fetched
        close cur_letters;
        all_letters_fetched = true;
        letter = null;
      end
    end
    
    if (all_numbers_fetched and all_letters_fetched) then
      leave;

    suspend;
  end
end
于 2018-08-14T09:04:37.390 回答