用于创建逗号分隔记录的 Oracle SQL 10g 查询
Oracle SQL 10g query for creating comma separated records
我正在编写用于创建 jasper 报告的 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" 的列来显示作者的经理。经理信息在 WRITER_TABLE 中,列名 "manager_name"。 essay_table 包含作者的名字、姓氏和用户名。棘手的部分是 2 个作者可以有 2 个不同的经理。
例如,对于论文'123',作者是'abc'和'xyz',这些作者的经理分别是'lmo'和'pqr',那么记录应按以下格式表示
essay id writer manager
123 abc, xyz lmo, pqr
这在 oracle 10g sql 中可行吗?
我试图搜索类似的情况,但没有找到任何相关的解决方案。
您可以只在最内层查询和中间查询中包含 manager_name
,然后也对该列重复聚合机制。我已将列和 table 别名更改为更加一致(并且我还简化了您的 case 表达式):
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
不过这可能是您想要看到的。
如果您确实想抑制重复的管理器,您可以将聚合分离到子查询中。我发现将这些拉入常见的 table 表达式(a.k.a。子查询重构)更容易阅读:
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
我正在编写用于创建 jasper 报告的 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" 的列来显示作者的经理。经理信息在 WRITER_TABLE 中,列名 "manager_name"。 essay_table 包含作者的名字、姓氏和用户名。棘手的部分是 2 个作者可以有 2 个不同的经理。 例如,对于论文'123',作者是'abc'和'xyz',这些作者的经理分别是'lmo'和'pqr',那么记录应按以下格式表示
essay id writer manager
123 abc, xyz lmo, pqr
这在 oracle 10g sql 中可行吗? 我试图搜索类似的情况,但没有找到任何相关的解决方案。
您可以只在最内层查询和中间查询中包含 manager_name
,然后也对该列重复聚合机制。我已将列和 table 别名更改为更加一致(并且我还简化了您的 case 表达式):
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
不过这可能是您想要看到的。
如果您确实想抑制重复的管理器,您可以将聚合分离到子查询中。我发现将这些拉入常见的 table 表达式(a.k.a。子查询重构)更容易阅读:
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