0

我正在编写一个用于创建碧玉报告的 oracle 10g 查询。

这是查询 -

SELECT     essay_id,
           LTRIM (
              MAX (SYS_CONNECT_BY_PATH (full_name, ','))
                 KEEP (DENSE_RANK LAST ORDER BY curr),
              ',')
              AS full_name
FROM       (SELECT essay_id,
                   full_name,
                   ROW_NUMBER () OVER (PARTITION BY essay_id ORDER BY full_name)
                      AS curr,
                     ROW_NUMBER ()
                        OVER (PARTITION BY essay_id ORDER BY full_name)
                   - 1
                      AS prev
            FROM   (SELECT a.id AS essay_id,
                           CASE NVL (firstname, 'NULL FIRSTNAME')
                              WHEN 'NULL FIRSTNAME' THEN username
                              ELSE (firstname || ' ' || lastname)
                           END
                              AS full_name
                    FROM   essay_table a
                           INNER JOIN essay_writer_join ej ON a.id = ej.essay_id
                           INNER JOIN writer_table u ON ej.user_id = u.id))
GROUP BY   essay_id
CONNECT BY prev = PRIOR curr AND essay_id = PRIOR essay_id
START WITH curr = 1

这些文章是独一无二的,但可以有多个作者 (essay_writer_join) 此查询为我提供了由逗号分隔的作者的文章。

问题是我需要再添加一个名为“manager”的列,它将显示作者的经理。经理信息位于列名为“manager_name”的 WRITER_TABLE 中。文章表有作者的名字、姓氏和用户名。棘手的部分是 2 位作家可以有 2 位不同的经理。例如,对于文章“123”,作者是“abc”和“xyz”,这些作者的管理者分别是“lmo”和“pqr”,那么记录应以下列格式显示

essay id      writer       manager
123          abc, xyz      lmo, pqr

这在 oracle 10g sql 中可能吗?我试图搜索类似的情况,但找不到任何相关的解决方案。

4

1 回答 1

1

您可以只manager_name在最内层查询和中间查询中包含 ,然后也为该列重复聚合机制。我已将列和表别名更改为更加一致(并且我还简化了您的案例表达式):

SELECT     essay_id,
           LTRIM (
              MAX (SYS_CONNECT_BY_PATH (writer, ','))
                 KEEP (DENSE_RANK LAST ORDER BY curr),
              ',')
              AS writer,
           LTRIM (
              MAX (SYS_CONNECT_BY_PATH (manager, ','))
                 KEEP (DENSE_RANK LAST ORDER BY curr),
              ',')
              AS manager
FROM       (SELECT essay_id,
                   writer,
                   manager,
                   ROW_NUMBER () OVER (PARTITION BY essay_id ORDER BY writer)
                      AS curr,
                     ROW_NUMBER ()
                        OVER (PARTITION BY essay_id ORDER BY writer)
                   - 1
                      AS prev
            FROM   (SELECT et.id AS essay_id,
                           CASE WHEN wt.firstname IS NULL THEN wt.username
                              ELSE (wt.firstname || ' ' || wt.lastname)
                           END
                              AS writer,
                           wt.manager_name as manager
                    FROM   essay_table et
                           INNER JOIN essay_writer_join ej ON et.id = ej.essay_id
                           INNER JOIN writer_table wt ON ej.user_id = wt.id))
GROUP BY   essay_id
CONNECT BY prev = PRIOR curr AND essay_id = PRIOR essay_id
START WITH curr = 1;

  ESSAY_ID WRITER     MANAGER  
---------- ---------- ----------
       123 abc,xyz    lmo,pqr   

我能看到的唯一真正的问题是,如果一篇文章的两位作者都有同一个经理;然后你会看到重复的值:

  ESSAY_ID WRITER     MANAGER  
---------- ---------- ----------
       123 abc,xyz    lmo,pqr   
       456 abc,def    lmo,lmo   

这可能是你想看到的。

SQL 小提琴演示

如果您确实想抑制重复的管理器,您可以将聚合分成子查询。我发现将这些引入公共表表达式(又名子查询重构)更容易阅读:

WITH all_data AS (
  SELECT et.id AS essay_id,
         CASE WHEN wt.firstname IS NULL THEN wt.username
            ELSE (wt.firstname || ' ' || wt.lastname)
         END
            AS writer,
         wt.manager_name as manager
  FROM   essay_table et
  JOIN   essay_writer_join ej ON et.id = ej.essay_id
  JOIN   writer_table wt ON ej.user_id = wt.id
),
writers AS (
  SELECT essay_id,
         writer,
         ROW_NUMBER () OVER (PARTITION BY essay_id ORDER BY writer) AS rn
  FROM   (
    SELECT distinct essay_id, writer
    FROM   all_data
  )
),
managers AS (
  SELECT essay_id,
         manager,
         ROW_NUMBER () OVER (PARTITION BY essay_id ORDER BY manager) AS rn
  FROM   (
    SELECT distinct essay_id, manager
    FROM   all_data
  )
)
SELECT   DISTINCT ad.essay_id,
         (
           SELECT     LTRIM (MAX (SYS_CONNECT_BY_PATH (w.writer, ','))
                        KEEP (DENSE_RANK LAST ORDER BY w.rn), ',')
           FROM       writers w
           WHERE      w.essay_id = ad.essay_id
           CONNECT BY w.rn = PRIOR w.rn + 1 AND w.essay_id = PRIOR w.essay_id
           START WITH w.rn = 1
         ) AS writer,
         (
           SELECT     LTRIM (MAX (SYS_CONNECT_BY_PATH (m.manager, ','))
                        KEEP (DENSE_RANK LAST ORDER BY m.rn), ',')
           FROM       managers m
           WHERE      m.essay_id = ad.essay_id
           CONNECT BY m.rn = PRIOR m.rn + 1 AND m.essay_id = PRIOR m.essay_id
           START WITH m.rn = 1
         ) AS manager
FROM     all_data ad
ORDER BY ad.essay_id;

重要的是,分配行号的每个子查询都使用自己的内联视图来获取不同的值。因此,对于获得的相同数据:

  ESSAY_ID WRITER     MANAGER  
---------- ---------- ----------
       123 abc,xyz    lmo,pqr   
       456 abc,def    lmo       

SQL 小提琴

于 2015-05-22T11:32:10.523 回答