检测oracle表中每行中具有相同值的所有列

Evi*_*ach 8 sql oracle oracle10g

每天,请求变得更奇怪和更奇怪.

我被要求组合一个查询来检测表中哪些列包含所有行的相同值.我说"这需要通过程序来完成,这样我们才能在表格的一次传递中完成,而不是N次传递."

我被推翻了.

长话短说.我有这个非常简单的查询来演示这个问题.它在测试集上进行了4次传递.我正在寻找SQL Magery的想法,它不涉及在每一列上添加索引,或编写程序,或者花费整个人的生命周期来运行.

感叹 它需要能够在任何工作表中.

提前感谢您的建议.

WITH TEST_CASE AS
(
    SELECT 'X' A, 5 B, 'FRI' C, NULL D FROM DUAL UNION ALL
    SELECT 'X' A, 3 B, 'FRI' C, NULL D FROM DUAL UNION ALL
    SELECT 'X' A, 7 B, 'TUE' C, NULL D FROM DUAL 
),
KOUNTS AS 
(
    SELECT SQRT(COUNT(*)) S, 'Column A' COLUMNS_WITH_SINGLE_VALUES
    FROM TEST_CASE P, TEST_CASE Q
    WHERE P.A = Q.A OR (P.A IS NULL AND Q.A IS NULL)

    UNION ALL

    SELECT SQRT(COUNT(*)) S, 'Column B' COLUMNS_WITH_SINGLE_VALUES
    FROM TEST_CASE P, TEST_CASE Q
    WHERE P.B = Q.B OR (P.B IS NULL AND Q.B IS NULL)

    UNION ALL

    SELECT SQRT(COUNT(*)) S, 'Column C' COLUMNS_WITH_SINGLE_VALUES
    FROM TEST_CASE P, TEST_CASE Q
    WHERE P.C = Q.C OR (P.C IS NULL AND Q.C IS NULL)

    UNION ALL

    SELECT SQRT(COUNT(*)) S, 'Column D' COLUMNS_WITH_SINGLE_VALUES
    FROM TEST_CASE P, TEST_CASE Q
    WHERE P.D = Q.D OR (P.D IS NULL AND Q.D IS NULL)
)
SELECT COLUMNS_WITH_SINGLE_VALUES
FROM KOUNTS
WHERE S = (SELECT COUNT(*) FROM TEST_CASE)
Run Code Online (Sandbox Code Playgroud)

muc*_*cio 10

你的意思是这样的吗?

WITH 
TEST_CASE AS
(
    SELECT 'X' A, 5 B, 'FRI' C, NULL D FROM DUAL UNION ALL
    SELECT 'X' A, 3 B, 'FRI' C, NULL D FROM DUAL UNION ALL
    SELECT 'X' A, 7 B, 'TUE' C, NULL D FROM DUAL 
)
select case when min(A) = max(A) THEN 'A'
            when min(B) = max(B) THEN 'B'
            when min(C) = max(C) THEN 'C'
            when min(D) = max(D) THEN 'D'
            else 'No one'
       end 
from TEST_CASE
Run Code Online (Sandbox Code Playgroud)

编辑 此作品:

WITH 
TEST_CASE AS
(
    SELECT 'X' A, 5 B, 'FRI' C, NULL D FROM DUAL UNION ALL
    SELECT 'X' A, 3 B, 'FRI' C, NULL D FROM DUAL UNION ALL
    SELECT 'X' A, 7 B, 'TUE' C, NULL D FROM DUAL 
)
select case when min(nvl(A,0)) = max(nvl(A,0)) THEN 'A ' end ||
       case when min(nvl(B,0)) = max(nvl(B,0)) THEN 'B ' end ||
       case when min(nvl(C,0)) = max(nvl(C,0)) THEN 'C ' end ||
       case when min(nvl(D,0)) = max(nvl(D,0)) THEN 'D ' end c

from TEST_CASE
Run Code Online (Sandbox Code Playgroud)

额外:我还添加了空值的检查,因此结果现在是:A和D.

SQLFiddle演示.


Jon*_*ler 8

优化程序统计信息可以轻松识别具有多个不同值的列.收集统计信息后,对数据字典的简单查询将立即返回结果.

如果使用ESTIMATE_PERCENT = 100,结果将仅在10g上准确.如果使用ESTIMATE_PERCENT = 100或AUTO_SAMPLE_SIZE,结果将在11g +上准确.

create table test_case(a varchar2(1), b number, c varchar2(3),d number,e number);

--I added a new test case, E.  E has null and not-null values.
--This is a useful test because null and not-null values are counted separately.
insert into test_case
SELECT 'X' A, 5 B, 'FRI' C, NULL D, NULL E FROM DUAL UNION ALL
SELECT 'X' A, 3 B, 'FRI' C, NULL D, NULL E FROM DUAL UNION ALL
SELECT 'X' A, 7 B, 'TUE' C, NULL D, 1    E FROM DUAL;

--Gather stats with default settings, which uses AUTO_SAMPLE_SIZE.
--One advantage of this method is that you can quickly get information for many
--tables at one time.
begin
    dbms_stats.gather_schema_stats(user);
end;
/

--All columns with more than one distinct value.
--Note that nulls and not-nulls are counted differently.
--Not-nulls are counted distinctly, nulls are counted total.
select owner, table_name, column_name
from dba_tab_columns
where owner = user
    and num_distinct + least(num_nulls, 1) <= 1
order by column_name;

OWNER     TABLE_NAME   COLUMN_NAME
-------   ----------   -----------
JHELLER   TEST_CASE    A          
JHELLER   TEST_CASE    D          
Run Code Online (Sandbox Code Playgroud)

性能

在11g上,这个方法可能与mucio的SQL语句一样快.这样的选项cascade => false可以通过不分析索引来提高性能.

但是这个方法的好处在于它还可以产生有用的统计数据.如果系统已经定期收集统计数据,则可能已经完成了艰苦的工作.

有关AUTO_SAMPLE_SIZE算法的详细信息

AUTO_SAMPLE_SIZE在11g中完全改变了.它不使用抽样来估计不同值(NDV)的数量.相反,它扫描整个表并使用基于散列的不同算法.该算法不需要大量内存或临时表空间.读取整个表格比快速排序要快得多.Oracle Optimizer博客在此处对算法有很好的描述.有关更多详细信息,请参阅Amit Podder的演示文稿.(如果要在下一节中验证详细信息,您需要浏览该PDF文件.)

错误结果的可能性

虽然新算法不使用简单的采样算法,但它仍然不能正确计算100%的不同值的数量.很容易找到估计的不同值的数量与实际值不同的情况.但是,如果不同值的数量明显不准确,那么它们如何在此解决方案中受到信任?

潜在的不准确性来自两个来源 - 哈希冲突和概要分裂.概要拆分是不准确的主要来源,但不适用于此处.只有当有13864个不同的值时才会发生这种情况.并且它永远不会抛弃所有的值,最终的估计肯定会远大于1.

唯一真正关心的是,有两个不同的值与哈希冲突的可能性是多少.使用64位散列,机会可能低至18,446,744,073,709,551,616中的1.不幸的是,我不知道他们的哈希算法的细节,也不知道真正的概率.我无法通过一些简单的测试和以前的现实测试产生任何碰撞.(我的一个测试是使用大值,因为一些统计操作只使用前N个字节的数据.)

现在还要考虑只有当表中的所有不同值发生冲突时才会发生这种情况.有一个表只有两个恰好碰撞的值的几率是多少?可能远远低于赢得彩票并同时受到陨石撞击的机会.