【问题标题】:Display two unrelated select queries with no mutual fields in one firebird procedure在一个 firebird 过程中显示两个不相关且没有相互字段的选择查询
【发布时间】:2018-08-14 07:58:15
【问题描述】:

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

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      

【问题讨论】:

  • 出于好奇:你为什么要做这样的事情?
  • 我必须在报告的一个 xtratable 中显示两个选择过程。我正在使用 devexpress,我认为这是最好的做法。在一个过程中组合两个选择查询

标签: sql select firebird firebird-3.0


【解决方案1】:

假设您想要一个“压缩”不相关集的结果集,您应该为任一表中的每一行分配一个行号(使用 Firebird 3 的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)

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 2016-04-16
    • 1970-01-01
    • 1970-01-01
    • 2018-10-06
    • 2011-12-02
    相关资源
    最近更新 更多