Oracle事务数据库:如何自动筛选存在多distinct值的列?
Oracle 批量筛选有数据变化的列解决方案
先纠正你原SQL的问题
你当前的写法会触发ORA-00979: 不是 GROUP BY 表达式错误,因为column1等列不在GROUP BY列表中,也没有使用聚合函数。如果你的需求是保留所有数据行并仅显示符合条件的列,不能用GROUP BY,而是要用窗口函数或者先筛选出整个表中存在变化的列。
场景1:保留整个表中存在数据变化的列(该列有多个distinct值)
如果你的需求是查询表的所有行,但只保留那些整个表内有多个不同值的列,无需手动写每一列,可通过Oracle数据字典生成动态SQL自动完成:
步骤1:生成动态查询语句
执行以下SQL(替换YOUR_TABLE_NAME为你的表名,注意Oracle表名默认大写):
SELECT 'SELECT ID, ' || RTRIM(XMLAGG(XMLELEMENT(E, column_name || ',')).EXTRACT('//text()'), ',') || ' FROM YOUR_TABLE_NAME' AS dynamic_sql FROM user_tab_columns WHERE table_name = 'YOUR_TABLE_NAME' AND column_name != 'ID' -- 如果ID是必须保留的主键,保留此行;否则删除 AND (SELECT COUNT(DISTINCT t." || column_name || ") FROM " || table_name || " t) > 1;
步骤2:执行生成的动态SQL
执行上述SQL后,会得到一条完整的查询语句,直接运行该语句即可得到所有行,且仅包含整个表中存在数据变化的列。
场景2:按ID分组后,仅显示每组内有数据变化的列
如果你的需求是:对于每个ID对应的多行数据,仅显示该ID组内存在多个不同值的列(其他列显示NULL),同样用动态SQL自动生成语句:
步骤1:生成动态查询语句
SELECT 'SELECT ID, ' || RTRIM(XMLAGG(XMLELEMENT(E, 'CASE WHEN COUNT(DISTINCT ' || column_name || ') OVER (PARTITION BY id) > 1 THEN ' || column_name || ' END AS ' || column_name || ',')).EXTRACT('//text()'), ',') || ' FROM YOUR_TABLE_NAME' AS dynamic_sql FROM user_tab_columns WHERE table_name = 'YOUR_TABLE_NAME' AND column_name != 'ID';
步骤2:执行生成的动态SQL
运行生成的语句后,每一行数据中,仅会显示对应ID组内有变化的列,无变化的列值为NULL。
内容的提问来源于stack exchange,提问作者Notacoder22
相关产品推荐
相关产品推荐

