当count(*)在乘法值上返回null时,如何获得0值

时间:2010-06-29 15:17:48

标签: sql oracle

我有一个包含错误代码和输入时间(以及其他内容)的表格 我需要的是一种方法来计算最后一小时具有相同错误代码(我选择)的行数,并将结果与​​错误代码串起来。

SELECT COUNT(*) || ',' || error_code as amount_and_code
FROM my_table
WHERE error_code in (5001, 5002, 5003, 5004, 5005)
AND entry_date >= (SYSDATE - 1/24)
group by error_code;

我得到了

的明显结果
AMOUNT_AND_CODE
---------------
4,5001
1,5002
2,5005

我的问题是:如何为未找到的值返回0,error_code 我想得到的是

AMOUNT_AND_CODE
---------------
4,5001
1,5002
0,5003
0,5004
2,5005

有没有办法获得我正在寻找的输出?

非常感谢你的帮助,mod。

编辑:我没有包含所有错误代码的表格 Edit2:Oracle8i企业版8.1.7.4.0版

7 个答案:

答案 0 :(得分:5)

您可以尝试这样的事情:

SQL> create table nnn(error_code varchar2(4), entry_date date);

Table created.

SQL> insert into nnn values (5001, sysdate);

1 row created.

SQL> insert into nnn values (5003, sysdate - 10);

1 row created.

SQL>
SQL> with tbl as
  2  (select 5001 error_code from dual union all
  3   select 5002 error_code from dual union all
  4   select 5003 error_code from dual union all
  5   select 5004 error_code from dual)
  6  select count(nnn.error_code), tbl.error_code
  7  from   nnn, tbl
  8  where  nnn.error_code(+) = tbl.error_code
  9  and    entry_date(+) >= (SYSDATE - 1/24)
 10  group  by tbl.error_code;

COUNT(NNN.ERROR_CODE) ERROR_CODE
--------------------- ----------
                    0       5003
                    1       5001
                    0       5002
                    0       5004

SQL>

答案 1 :(得分:4)

你有错误代码表吗?如果是这样,那么你可以这样做:

SELECT COUNT(my_table.id) || ',' || e.error_code as amount_and_code
FROM error_codes e
LEFT OUTER JOIN my_table ON my_table.error_code = e.error_code
                        AND my_table.entry_date >= (SYSDATE - 1/24)
WHERE e.error_code in (5001, 5002, 5003, 5004, 5005)
group by e.error_code;

如果没有,请尝试:

WITH error_codes as
    ( SELECT 5001 FROM DUAL
      UNION ALL
      SELECT 5002 FROM DUAL
      UNION ALL
      SELECT 5003 FROM DUAL
      UNION ALL
      SELECT 5004 FROM DUAL
      UNION ALL
      SELECT 5005 FROM DUAL
    )
SELECT COUNT(my_table.id) || ',' || e.error_code as amount_and_code
FROM error_codes e
LEFT OUTER JOIN my_table ON my_table.error_code = e.error_code
                        AND my_table.entry_date >= (SYSDATE - 1/24)
group by e.error_code;

答案 2 :(得分:2)

你试过......

SELECT NVL (COUNT(*), 0) || ',' || error_code as amount_and_code
    FROM my_table
    WHERE error_code in (5001, 5002, 5003, 5004, 5005) AND
          entry_date >= (SYSDATE - 1/24)
GROUP BY error_code;

答案 3 :(得分:2)

错误代码是否总是按顺序排列?在这种情况下,您应该能够使用连接:

   SELECT COUNT(MY_TABLE.ERROR_CODE) || ',' || ERROR_CODES.error_code as amount_and_code
FROM 
    (
        SELECT (5000+LEVEL) error_code 
        FROM DUAL 
        CONNECT BY LEVEL <= 5    
    ) ERROR_CODES
    LEFT JOIN
    (
        SELECT 5001 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
        UNION ALL
        SELECT 5001 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
        union all
        SELECT 5001 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
        union all
        SELECT 5001 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
        union all
        SELECT 5002 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
        union all
        SELECT 5005 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
        UNION all
        SELECT 5005 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
    ) MY_TABLE
      ON MY_TABLE.ERROR_CODE        = ERROR_CODES.ERROR_CODE
           AND MY_TABLE.ENTRY_DATE >= (SYSDATE - 1/24)
GROUP BY       ERROR_CODES.ERROR_CODE
order by  ERROR_CODES.error_code
;

如果您只想显示所有错误,可以尝试使用

with MY_TABLE as(
        SELECT 5001 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
        UNION ALL
        SELECT 5001 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
        union all
        SELECT 5001 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
        union all
        SELECT 5001 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
        union all
        SELECT 5002 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
        union all
        SELECT 5005 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
        UNION ALL
        SELECT 5005 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
        UNION ALL
        SELECT 5003 ERROR_CODE, (SYSDATE - 1/23) ENTRY_DATE FROM DUAL
        UNION ALL
        SELECT 5004 ERROR_CODE, (SYSDATE - 1/23) ENTRY_DATE FROM DUAL
        UNION ALL
        SELECT 5006 ERROR_CODE, (SYSDATE - 1/23) ENTRY_DATE FROM DUAL
        UNION ALL
        SELECT 5010 ERROR_CODE, (SYSDATE - 1/23) ENTRY_DATE FROM DUAL
        UNION ALL
        SELECT 6018 ERROR_CODE, (SYSDATE - 1/23) ENTRY_DATE FROM DUAL        
) 
 SELECT COUNT(MY_TABLE.ERROR_CODE) || ',' || ERROR_CODES.error_code as amount_and_code
FROM 
    (
        SELECT DISTINCT ERROR_CODE
        FROM MY_TABLE --**warning** this could be resource intensive    
    ) ERROR_CODES
    LEFT JOIN
     MY_TABLE
      ON MY_TABLE.ERROR_CODE        = ERROR_CODES.ERROR_CODE
           AND MY_TABLE.ENTRY_DATE >= (SYSDATE - 1/24)
GROUP BY       ERROR_CODES.ERROR_CODE
order by  ERROR_CODES.error_code
;

这实际上只是让您对表格中的所有错误代码进行区分,然后根据时间选择计数

        (
        SELECT DISTINCT ERROR_CODE
        FROM MY_TABLE --**warning** this could be resource intensive    
    ) ERROR_CODES

请注意,这可能是资源密集型的

如果你只想要特定的数字(即5001,5002,5003,####,#### 2,...,### x)那么你可以试试这样的东西(这需要一个自定义类型和要创建的函数):

--see  http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:210612357425
--create a table of numbers ,create a function to split the "where" into a table
--then return the data
CREATE OR REPLACE type numberTableType as table      of number;
/
create or replace function in_number(  p_string in varchar2 ) return numberTableType  AS
        l_string        long default p_string || ',';
        l_data          numberTableType := numberTableType();
        l_number        number ;
        N               NUMBER;
    BEGIN

      loop
          exit when l_string is null;
          n := instr( l_string, ',' );
         l_data.extend;
         begin --is user inputs a non-numeric value  skip the value
            l_number := cast(ltrim( rtrim( substr( l_string, 1, n-1 ) ) )  as number);
            l_data(l_data.count) := l_number ;
            EXCEPTION
                    WHEN VALUE_ERROR THEN
                        l_number := 0;
                    WHEN OTHERS THEN
                        raise ;
         end ;
         l_string := substr( l_string, n+1 );
    end loop;
    RETURN L_DATA;
  END in_number;
  /

 SELECT COUNT(MY_TABLE.ERROR_CODE) || ',' || ERROR_CODES.error_code as amount_and_code
FROM 
    (
        SELECT COLUMN_VALUE AS ERROR_CODE 
          from table(in_number('5001,5002,5003,5004,5005,5010'))    
    ) ERROR_CODES
    LEFT JOIN
        (
            SELECT 5001 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
            UNION ALL
            SELECT 5001 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
            union all
            SELECT 5001 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
            union all
            SELECT 5001 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
            union all
            SELECT 5002 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
            union all
            SELECT 5005 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
            UNION ALL
            SELECT 5005 ERROR_CODE, (SYSDATE - 1/26) ENTRY_DATE FROM DUAL
            UNION ALL
            SELECT 5003 ERROR_CODE, (SYSDATE - 1/23) ENTRY_DATE FROM DUAL
            UNION ALL
            SELECT 5004 ERROR_CODE, (SYSDATE - 1/23) ENTRY_DATE FROM DUAL
            UNION ALL
            SELECT 5006 ERROR_CODE, (SYSDATE - 1/23) ENTRY_DATE FROM DUAL
            UNION ALL
            SELECT 5010 ERROR_CODE, (SYSDATE - 1/23) ENTRY_DATE FROM DUAL
            UNION ALL
            SELECT 6018 ERROR_CODE, (SYSDATE - 1/23) ENTRY_DATE FROM DUAL            
        )
     MY_TABLE
      ON MY_TABLE.ERROR_CODE        = ERROR_CODES.ERROR_CODE
           AND MY_TABLE.ENTRY_DATE >= (SYSDATE - 1/24)
GROUP BY       ERROR_CODES.ERROR_CODE
ORDER BY  ERROR_CODES.ERROR_CODE
;  

答案 4 :(得分:2)

我希望entry_date >= (SYSDATE - 1/24) 过滤您需要的记录(即5003&amp; 5004)。

删除该条件并检查结果。

尝试以下查询,它可以解决您的问题

SELECT COUNT(error_code) || ',' || error_code as amount_and_code 
    FROM my_table 
    WHERE error_code in (5001, 5002, 5003, 5004, 5005) AND 
          entry_date >= (SYSDATE - 1/24) 
GROUP BY error_code; 

答案 5 :(得分:1)

提出一个请求,就好像你有一个extern表,没有在Oracle 8中没有'WITH'... 与Tony的代码非常相似:

SELECT COUNT(t1.error_code) || ',' || t2.error_code as amount_and_code
FROM my_table t right outer join 
                    (
                        select 5001 as error_code from dual
                        union
                        select 5002 as error_code from dual
                        union
                        select 5003 as error_code from dual
                        union
                        select 5004 as error_code from dual
                        union
                        select 5005 as error_code from dual
                    ) t2 on t1.error_code = t2.error_code
                         and t.entry_date >= (SYSDATE - 1/24)
group by t2.error_code;

答案 6 :(得分:0)

您是否有一个列出错误代码的主表?如果是这样,我会外连接到该表,以便保证为每个条目返回一行。