【问题标题】:How to retrieve only columns which have at least one not null value in any row in Oracle如何仅检索Oracle中任何行中至少具有一个非空值的列
【发布时间】:2018-10-13 15:30:57
【问题描述】:

我的表结构和数据如下 https://ibb.co/mkGp67

我想要一个 SQL 查询只为那些至少有一个非空值的列检索数据,在上述情况下,我希望数据出来

https://ibb.co/mz9967

即我不需要 Col2、Col5 和 Col6 列,而且哪一列全为空值也不固定。

请让我知道 SQL 查询,它检索的数据只有那些不具有上述数据的空值的列。

【问题讨论】:

  • 请不要提供示例数据的图片。只有文本格式。另外,发布您尝试过的查询。
  • 我正在尝试加载图像但无法加载
  • 请不要发布指向未知页面的链接。编辑您的问题并将文本粘贴到问题中,formatting it as needed。谢谢。
  • Kaushik Nayak 的意思是您应该根本不使用图像,而是将数据作为文本发布,例如通过提供 CREATE TABLE & INSERT 语句,或通过使用代码格式化和以 ASCII 样式绘制表格。

标签: oracle oracle11g oracle10g


【解决方案1】:

据我所知,您无法通过 SQL 查询来实现这一点。 SELECT 语句的强假设之一是返回的列列表是静态的 - 在查询中定义,而不是由数据定义。即使对于 PIVOT 查询(据我所知,自 Oracle 11 以来可用),列列表也是在查询中定义的,通过提供要转换为列的值列表,必须明确给出。

您正在寻找的是某种代码,动态生成查询。这可以是 PL/SQL,返回游标引用或任何应用程序代码。

编辑:

您可以对查询做的事情是清楚地了解哪些列包含空值,哪些列不包含空值等。它可能看起来像这样:

SELECT CASE
         WHEN COUNT(*) = 0 THEN 'no rows'
         WHEN COUNT(Col1) = 0 THEN 'all NULLs'
         WHEN COUNT(Col1) = COUNT(*) THEN 'no NULLs'
         ELSE 'some NULLs'
       END Col1NullStatus,
       CASE
         WHEN COUNT(*) = 0 THEN 'no rows'
         WHEN COUNT(Col2) = 0 THEN 'all NULLs'
         WHEN COUNT(Col2) = COUNT(*) THEN 'no NULLs'
         ELSE 'some NULLs'
       END Col2NullStatus,
       CASE
         WHEN COUNT(*) = 0 THEN 'no rows'
         WHEN COUNT(Col3) = 0 THEN 'all NULLs'
         WHEN COUNT(Col3) = COUNT(*) THEN 'no NULLs'
         ELSE 'some NULLs'
       END Col3NullStatus,
       CASE
         WHEN COUNT(*) = 0 THEN 'no rows'
         WHEN COUNT(Col4) = 0 THEN 'all NULLs'
         WHEN COUNT(Col4) = COUNT(*) THEN 'no NULLs'
         ELSE 'some NULLs'
       END Col4NullStatus,
       CASE
         WHEN COUNT(*) = 0 THEN 'no rows'
         WHEN COUNT(Col5) = 0 THEN 'all NULLs'
         WHEN COUNT(Col5) = COUNT(*) THEN 'no NULLs'
         ELSE 'some NULLs'
       END Col5NullStatus,
       CASE
         WHEN COUNT(*) = 0 THEN 'no rows'
         WHEN COUNT(Col6) = 0 THEN 'all NULLs'
         WHEN COUNT(Col6) = COUNT(*) THEN 'no NULLs'
         ELSE 'some NULLs'
       END Col6NullStatus
  FROM myTable

SQL Fiddle for the above

编辑 2:

这个查询的输出看起来像这样:

Col1Null状态 | Col2Null状态 | Col3NullStatus | Col4Null状态 | Col5NullStatus | Col6NullStatus ---------------+----------------+----------------+ ----------------+----------------+---------------- 没有空值 |所有 NULL |一些空值 |没有空值 |所有 NULL |所有 NULL

这是您可以用来发布输入数据和预期结果的格式。

【讨论】:

  • 这条评论与答案有什么关系?
  • 非常感谢 Hilarion 先生,我只想不显示空值和一些空值列并隐藏所有空值列
  • @zahidgs:正如我在答案中所写,我认为仅使用 SQL 查询是不可能的。您可以使用我在您的应用程序代码(或 PL/SQL)中的答案中给出的查询来动态构建一个查询,该查询只有与您的条件匹配的列。
  • @zahidgs:同样,提出问题和提供答案的 StackOverflow 规则是在 StackOverflow 上而不是在外部服务中提供必要的信息。这些仍然可以作为附加帮助引用,以支持任何声明等。我们已经向您展示了如何在此处发布数据,并且我已经告诉过您,您所询问的似乎不可行通过一个静态 SQL 查询。
【解决方案2】:

因此,由于您没有给出正式的表结构,而且您似乎混淆了数字和字符,因此我会尽力尝试进行查询,至少会产生您想要的结果。

创建表 foo 为 ( col1 varchar(10), col2 varchar(10), col3 varchar(10), col4 varchar(10), col5 varchar(10), col6 varchar(10) );

选择 * CASE cust1 WHEN null then 'null' else cust1 as cust1 end, CASE cust2 WHEN null then 'null' else cust1 as cust1 end, CASE cust3 WHEN null then 'null' else cust1 as cust1 end, CASE cust4 WHEN null then 'null' else cust1 as cust1 end, CASE cust5 WHEN null then 'null' else cust1 as cust1 end, CASE cust6 WHEN null then 'null' else cust1 as cust1 end 来自 foo ;

【讨论】:

    【解决方案3】:
    As per below query , I able to get not null columns at row-level col1,col3 and col4.
    
    Query :
    select 'col1' as "Name",col1 from temp
     where  exists (select  1 
     from temp
     group by to_char(col1)
     having (count(to_char(col1)))> 0)
     union all 
     select 'col2' as "Name",to_char(col2) from temp
     where  exists (select  1 
     from temp
     group by to_char(col2)
     having (count(to_char(col2)))> 0)
     union all
     select 'col3' as "Name" , to_char(col3) from temp
     where  exists (select  1 
     from temp
     group by to_char(col3)
     having (count(to_char(col3)))> 0)
     union all
     select 'col4'as "Name" , to_char(col4) from temp
     where  exists (select  1 
     from temp
     group by to_char(col4)
     having (count(to_char(col4)))> 0)
     union all
     select 'col5' as "Name" , to_char(col5) from temp
     where  exists (select  1 
     from temp
     group by to_char(col5)
     having (count(to_char(col5)))> 0)
     union all
     select 'col6' as "Name" , to_char(col6) from temp
     where  exists (select  1 
     from temp
     group by to_char(col6)
     having (count(to_char(col6)))> 0)
    
    output:
    
    col1    A
    col1    B
    col1    C
    col1    D
    col3    10
    col3    20
    col3     - 
    col3    10
    col4    12
    col4    23
    col4    34
    col4    43
    
    I tried to make this output of rows to columns but I couldn't make it in single query ... Hope this will be helpful ... 
    

    【讨论】:

      【解决方案4】:

      我通常会分三个步骤完成此操作。

      首先,确保表格统计信息是最新的。检查last_analyzed 是否晚于对表格的最后一次更改。

      SELECT last_analyzed FROM user_tables WHERE table_name = 'MYTABLE';
      

      如有疑问,请更新统计信息

      BEGIN dbms_stats.gather_table_stats('MYSCHEMA','MYTABLE'); END;
      /
      

      现在,视图user_tab_columns 有一个列num_nulls。这是此列为NULL 的行数。如果该值与表中的行数相同,则所有行都是NULL。这可用于让 Oracle 生成所需的 SQL:

      WITH 
        qtab AS (SELECT owner, table_name, num_rows
                   FROM all_tables 
                  WHERE owner='SCOTT'            -- change to your schema
                    AND table_name='EMPLOYEES'   -- change to your table name
                 ),
        qcol AS (SELECT owner, table_name, column_name, column_id
                   FROM qtab t 
                   JOIN all_tab_columns c USING (owner, table_name)
                  WHERE c.nullable = 'N'         -- protected by NOT NULL constraint 
                     OR c.num_nulls = 0          -- never NULL
                     OR c.num_nulls < t.num_rows -- at least 1 row is NOT NULL
                    )  
                    )  
      SELECT 'SELECT '||LISTAGG(column_name,',') WITHIN GROUP (ORDER BY column_id)||
              ' FROM '||owner||'.'||table_name||';' AS my_query
        FROM qcol
       GROUP BY owner, table_name;
      

      这将输出类似

      的查询
      SELECT col1, col3, col4, col5 FROM myschema.mytable;
      

      现在可以执行此查询以显示列值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-22
        • 1970-01-01
        • 2017-10-20
        相关资源
        最近更新 更多