即使不存在也输出具有空值的记录

Output records with null values even if not present

我在 Oracle

中有一个 table,如下所示
gen_id serial_code is_verified
1 fmcg Y
1 smcg Y
1 xmcg N
2 smcg Y
2 fmcg Y
2 2mcg Y
3 smcg Y
3 amcg Y

现在我想要最大 gen_id 的输出,在本例中为 3,serial_code 'smcg' 和 'fmcg' 我可以通过查询轻松获得输出,但我希望它采用如下格式。

gen_id serial_code is_verified
3 smcg Y
3 fmcg not_present

我怎样才能做到这一点?任何帮助深表感谢。 提前致谢

这样就可以了,但是看起来不是很漂亮。阅读代码中的注释。

SQL> WITH
  2     test (gen_id, serial_code, is_verified)
  3     AS
  4     -- sample data
  5        (SELECT 1, 'fmcg', 'Y' FROM DUAL
  6         UNION ALL
  7         SELECT 1, 'smcg', 'Y' FROM DUAL
  8         UNION ALL
  9         SELECT 1, 'xmcg', 'N' FROM DUAL
 10         UNION ALL
 11         SELECT 3, 'smcg', 'Y' FROM DUAL
 12         UNION ALL
 13         SELECT 3, 'amcg', 'Y' FROM DUAL),

 14     maxgen (gen_id)
 15     AS
 16     -- MAX gen_id value; will be used later
 17     (SELECT MAX (gen_id) FROM test),
 18     temp
 19     AS
 20        -- compose NOT_PRESENT rows that don't exist in original (TEST) table
 21        (SELECT t.gen_id, c.serial_code, 'not_present' is_verified
 22           FROM test t
 23                CROSS JOIN (SELECT DISTINCT serial_code
 24                              FROM test) c
 25                JOIN maxgen m
 26                   ON     m.gen_id = t.gen_id
 27                      AND (t.gen_id, c.serial_code) NOT IN
 28                             (SELECT gen_id, serial_code FROM test))
 29  -- finally: union existing rows (from TEST) with NOT_PRESENT ones (from TEMP)
 30  SELECT a.gen_id, a.serial_code, a.is_verified
 31    FROM test a JOIN maxgen m ON m.gen_id = a.gen_id
 32   WHERE serial_code IN ('smcg', 'fmcg')
 33  UNION
 34  SELECT x.gen_id, x.serial_code, x.is_verified
 35    FROM temp x
 36   WHERE x.serial_code IN ('smcg', 'fmcg');

    GEN_ID SERIAL_CODE  IS_VERIFIED
---------- ------------ -----------
         3 fmcg         not_present
         3 smcg         Y

SQL>

您可以为此使用 PARTITIONed OUTER JOIN

来自 Oracle 12:

SELECT t.gen_id,
       s.serial_code,
       COALESCE(t.is_verified, 'not_present') AS is_verified
FROM   (SELECT 'smcg' AS serial_code FROM DUAL UNION ALL
        SELECT 'fmcg' FROM DUAL) s
       LEFT OUTER JOIN (
         SELECT *
         FROM   table_name
         ORDER BY gen_id DESC
         FETCH FIRST ROW WITH TIES
       ) t
       PARTITION BY (gen_id)
       ON (s.serial_code = t.serial_code)

在 Oracle 11 中,您可以使用:

SELECT t.gen_id,
       s.serial_code,
       COALESCE(t.is_verified, 'not_present') AS is_verified
FROM   (SELECT 'smcg' AS serial_code FROM DUAL UNION ALL
        SELECT 'fmcg' FROM DUAL) s
       LEFT OUTER JOIN (
         SELECT gen_id, serial_code, is_verified
         FROM   (
           SELECT t.*,
                  RANK() OVER (ORDER BY gen_id DESC) AS rnk
           FROM   table_name t
         )
         WHERE  rnk = 1
       ) t
       PARTITION BY (gen_id)
       ON (s.serial_code = t.serial_code)

其中,对于示例数据:

CREATE TABLE table_name (gen_id, serial_code, is_verified) AS
SELECT 1, 'fmcg', 'Y' FROM DUAL UNION ALL
SELECT 1, 'smcg', 'Y' FROM DUAL UNION ALL
SELECT 1, 'xmcg', 'N' FROM DUAL UNION ALL
SELECT 2, 'smcg', 'Y' FROM DUAL UNION ALL
SELECT 2, 'fmcg', 'Y' FROM DUAL UNION ALL
SELECT 2, '2mcg', 'Y' FROM DUAL UNION ALL
SELECT 3, 'smcg', 'Y' FROM DUAL UNION ALL
SELECT 3, 'amcg', 'Y' FROM DUAL;

双输出:

   PARTITION BY (gen_id)
   ON (s.serial_code = t.serial_code)
GEN_ID SERIAL_CODE IS_VERIFIED
3 fmcg not_present
3 smcg Y

Oracle 18 数据库<>fiddle here - Oracle 11 db<>fiddle here