如何将所有记录合并为一行 |甲骨文 SQL |

How to combine all records into one row | ORACLE SQL |

我一直在尝试这样做,但无法使用 list_agg

我有 1 个 table 其中包含所有 table 个名字

Table 姓名:get_tables

下面是 get_tables 中的所有 table 个名字。获取 tables 作为名为 tbl_names

的列
tbl_names
--------------

EMP_1

EMP_2

STUD_1

STUD_2

DEMO_1

STUDENT_DETAILS

我写了一个综合查询来获取所有 tables 计数

select 'SELECT ' ||  '''' || tbl_names || '''' || ' AS TBL , COUNT(*) as CNT FROM  from  tbl_names || 'union'  from get_tables;

基本上我生成下面的查询作为上面查询的输出

   0 SELECT 'EMP_1' AS TBL , COUNT(*) from EMP_1 union
   1 SELECT 'EMP_2' AS TBL , COUNT(*) from EMP_2 union
   2 SELECT 'STUD_1' AS TBL , COUNT(*) from STUD_1 union
   3 SELECT 'STUD_2' AS TBL , COUNT(*) from STUD_1 union
   4 SELECT 'DEMO_1' AS TBL , COUNT(*) from DEMO_1 union
   5 SELECT 'STUDENT_DETAILS' AS TBL , COUNT(*) from STUDENT_DETAILS union

现在我首先要查询的两件事是记录
需要将所有组合为一个查询并从最后一行删除最后一个关键字 union 并替换为 ';'

所以这个生成的查询我可以 运行 从我的 python 脚本中一次性获得所有 table 计数 table name

预期输出:

TABLE         COUNT 
EMP_1           10 
EMP_2           20
STUD_1          40 
STUD_2          50
DEMO_1          50 
STUDENT_DETAILS 100 

为什么不直接查询 all_tables table(或 user_tables 或 dba_tables),它已经保存了每个 table 的行数?

SELECT TABLE_NAME, NUM_ROWS
FROM ALL_TABLES;

这里介绍一种方法,用LISTAGG来说明方法。如果 table 太多,您将需要一种不同的聚合方式(例如 XMLAGG),但这是一个不同的问题 - 您可以在 SO 上找到数百个相关问题。

最好使用UNION ALL而不是UNION,但如果你坚持只使用UNION,你可以自己修改解决方案。使用 LISTAGG,但不要在要聚合的标记中包含 UNION [ALL];相反,将其用作 分隔符 !

为了更容易阅读输出,我还在分隔符中包含了一个换行符;除了调试外不需要。在您对查询按预期工作感到满意后,您可以选择将其删除。

另外,我也懒得在末尾连接一个分号;你可以自己添加。

注意 - 输出是单行,意味着包含换行符的单个字符串(因此显示为多行文本)。它没有分布在多个 上,它只是一行中单个字符串中的几行。

EDIT 再次查看,我发现您的个别 SELECT 语句不正确(它们显示关键字“from”两次,所有 SELECT 语句正在计算 get_tables table 中的行数,而不是每个 table 中的行数,也许还有其他错误)。我会让你改正所有这些错误;它们与您问题的主要主题无关,该主题是关于以所需方式汇总陈述 - 无论正确与否。

结束编辑(在答案底部进一步编辑)

with get_tables (tbl_names) as (
  select 'EMP_1'           from dual union all
  select 'EMP_2'           from dual union all
  select 'STUD_1'          from dual union all
  select 'STUD_2'          from dual union all
  select 'STUD_3'          from dual union all
  select 'STUDENT_DETAILS' from dual
)
-- end of sample data, for testing only; remove WITH clause
-- and use your actual table and column names.
select listagg('SELECT ' ||  '''' || tbl_names || '''' ||
         ' AS TBL , COUNT(*) as CNT FROM  from  tbl_names',
               ' union all' || chr(10))
         within group (order by tbl_names) as sql_str
from get_tables;

SQL_STR                                                                           
----------------------------------------------------------------------------------
SELECT 'EMP_1' AS TBL , COUNT(*) as CNT FROM  from  tbl_names union all
SELECT 'EMP_2' AS TBL , COUNT(*) as CNT FROM  from  tbl_names union all
SELECT 'STUDENT_DETAILS' AS TBL , COUNT(*) as CNT FROM  from  tbl_names union all
SELECT 'STUD_1' AS TBL , COUNT(*) as CNT FROM  from  tbl_names union all
SELECT 'STUD_2' AS TBL , COUNT(*) as CNT FROM  from  tbl_names union all
SELECT 'STUD_3' AS TBL , COUNT(*) as CNT FROM  from  tbl_names

第二次编辑

OP 的用例需要生成 CLOB,因此 LISTAGG 将不起作用。以下是如何修改查询以使其适用于 CLOB 输出。我同时更正了声明 - 在第一个代码块之前查看我的第一个编辑。

为了确保它能正常工作,我在我的架构中为 ALL_TABLES 视图编写了它; table 个名字在名为 TABLE_NAME 的列中。 OP 应该为他的用例更改这些名称。

select regexp_replace(
         xmlcast(xmlagg(xmlelement(e, 
           'select ''' || table_name || ''' as tbl, count(*) as cnt from '
           || table_name, ' union all ' || chr(10))) as clob),
       ' union all ' || chr(10) ||'$', ';')
       as sql_string
from   all_tables;

结束第二次编辑