Есть ли способ иметь два разных предложения where в одной процедуре выбора в Interbase firebird?

Есть ли способ иметь два разных предложения where в одной процедуре выбора в Interbase firebird?

Я создал две таблицы, которые будут поддерживать этот вопрос. Желаемый вывод состоит в том, что процедура выбора будет отображать все данные из таблицы SAMPLE_SINGLE, даже если в таблице SAMPLE_DOUBLE нет SINGLE_PK.

CREATE TABLE SAMPLE_SINGLE (   
  SINGLE_PK SMALLINT NOT NULL,   
  SINGLE_NAME VARCHAR(50) CHARACTER SET ISO8859_1 COLLATE ISO8859_1,
  SINGLE_AMOUNT SMALLINT,   
  SINGLE_QUANTITY SMALLINT);

CREATE TABLE SAMPLE_DOUBLE (
  DOUBLE_PK SMALLINT NOT NULL,
  SINGLE_PK SMALLINT,
  DOUBLE_QUANTITY SMALLINT);


CREATE PROCEDURE SELECT_FROM2TABLES
RETURNS(
  SINGLE_NAME VARCHAR(50) CHARACTER SET ISO8859_1 COLLATE ISO8859_1,
  SINGLE_AMOUNT SMALLINT,
  SINGLE_QUANTITY SMALLINT,
  TOTAL_DOUBLE_QUANTITY SMALLINT,
  REMAINING_QUANTITY SMALLINT)
AS
BEGIN
  FOR
    SELECT
      A.SINGLE_NAME,
      A.SINGLE_AMOUNT,
      A.SINGLE_QUANTITY,
      SUM(B.DOUBLE_QUANTITY),
      A.SINGLE_QUANTITY - SUM(B.DOUBLE_QUANTITY)

    FROM SAMPLE_SINGLE A, SAMPLE_DOUBLE B
     WHERE A.SINGLE_PK = B.SINGLE_PK

    GROUP BY
     A.SINGLE_NAME,
      A.SINGLE_AMOUNT,
      A.SINGLE_QUANTITY

    INTO
      :SINGLE_NAME,
      :SINGLE_AMOUNT,
      :SINGLE_QUANTITY,
      :TOTAL_DOUBLE_QUANTITY,
      :REMAINING_QUANTITY
  DO
    BEGIN
      SUSPEND;
    END
END;

Для этой процедуры выбора будут отображаться только данные из таблицы SAMPLE_SINGLE, которая имеет SINGLE_PK, присутствующую в таблице SAMPLE_DOUBLE, из-за

FROM SAMPLE_SINGLE A, SAMPLE_DOUBLE B
         WHERE A.SINGLE_PK = B.SINGLE_PK

Я также хочу отображать данные из таблицы A, которых нет в таблице B.

Вот пример данных,

Table A (SAMPLE_SINGLE) SINGLE_PK  SINGLE_NAME SINGLE_AMOUNT SINGLE_QUNATITY
                          1          asdf          100            5
                          2          qwer          50             7
Table B (SAMPLE_DOUBLE) DOUBLE_PK  SINGLE_PK DOUBLE_QUANTITY
                          1            1           3 

Мой желаемый результат в процедуре выбора,

SINGLE_NAME SINGLE_AMOUNT SINGLE_QUANTITY TOTAL_DOUBLE_QUANTITY RMAINING_QUANTITY
    asdf          100            5               3                   2
    qwer          50             7               0                   7

Вот фактический результат для вышеуказанной процедуры, поскольку WHERE A.SINGLE_PK = B.SINGLE_PK будет отображать только первую строку

SINGLE_NAME SINGLE_AMOUNT SINGLE_QUANTITY TOTAL_DOUBLE_QUANTITY RMAINING_QUANTITY
    asdf          100            5               3                   2

person Don Juan    schedule 07.05.2017    source источник
comment
Interbase и Firebird — это не одна и та же система баз данных. За последние 18 лет они сильно разошлись, поэтому нельзя полагаться на то, что ответ на один из них применим и к другому. Так что выбирай: Firebird или interbase   -  person Mark Rotteveel    schedule 07.05.2017


Ответы (1)


Проблема в том, что вы используете неявное соединение (в стиле SQL-89), и равенство в where автоматически исключает те строки, в которых нет строки в B. Вместо этого вам нужно использовать явное соединение (в стиле SQL-92), а именно left outer join:

Внешнее соединение LEFT включает все записи из левого набора, но только совпадающие записи из правого набора.

Так что используйте:

FROM SAMPLE_SINGLE A
LEFT OUTER JOIN SAMPLE_DOUBLE B ON A.SINGLE_PK = B.SINGLE_PK

См. также Присоединяется к Справочнику по языку Firebird 2.5.

person Mark Rotteveel    schedule 07.05.2017