23

我需要计算列上的不同值,例如:

Hours
1
1
2
null
null
null

结果必须是:3。我的查询是:

select count(distinct hour) from hours;

但它返回:2.我也测试过:

select count(*) from hours group by hour

但它返回三行:

(1) 3
(2) 2
(3) 1

如何将空值计为 1 值并使用 distinct 来避免计算重复值?

我正在学习高级 SQL,他们希望我满足所有解决方案的这些要求:

尽量减少解决查询所需的子查询数量。此外,您不得使用以下结构:

  • 在 FROM 或 SELECT 中选择。您可以有子查询(在 WHERE 或 HAVING 中选择)
  • COUNT(COUNT...))、SUM(COUNT...))等聚合函数的组合。
  • 如果可以避免的话,请使用 UNION。
  • 非标准功能(如 NVL)
  • 案子
4

11 回答 11

34
select  count(distinct col1) + count(distinct case when col1 is null then 1 end)
from    YourTable
于 2013-02-23T12:39:12.000 回答
19

如果小时是一个数字,那么如果它只能是一个整数:

select count(distinct coalesce(hour, 0.1)) cnt from test;

否则,如果它可以是任何浮点数,请将 NULL 更改为 char 字符串。

例如

select count(distinct coalesce(to_char(hour), 'a')) cnt from test;
于 2013-02-24T00:18:58.133 回答
8
select 
   count(0) 
from
  (
      select distinct hour from hours
  )

SqlFiddle

于 2013-02-23T12:55:54.097 回答
3
SELECT
      ( SELECT COUNT(DISTINCT hour)
        FROM hours
      )
    + CASE WHEN EXISTS
           ( SELECT *
             FROM hours
             WHERE hour IS NULL
           )
        THEN 1 
        ELSE 0
      END
   AS result
FROM dual ;
于 2013-02-23T13:06:07.223 回答
2

也许

    select count(distinct hour||' ') from hours;

会做?

于 2013-09-09T15:00:18.557 回答
2
select count(distinct nvl(hour,0)) from hours;
于 2017-10-03T09:08:32.627 回答
1

我想说您的要求非常奇怪,因为您几乎可以肯定只需使用NVL(),COALESCE()或即可获得更有效的查询CASE。但是,我设法仅使用子查询来获得正确的结果(并处理NULL值的存在或不存在)。如果没有在子句中使用子查询,我还没有设法做到这一点FROM

SQL小提琴

查询 1

SELECT nnh.not_null_hours + nh.null_hours
FROM (
  SELECT COUNT(DISTINCT t.hour) not_null_hours
  FROM example_table t
) nnh
CROSS JOIN (
  SELECT 1 null_hours
  FROM dual
  WHERE EXISTS (
    SELECT 1
    FROM example_table t
    WHERE t.hour IS NULL
  )
  UNION ALL
  SELECT 0 null_hours
  FROM dual
  WHERE NOT EXISTS (
    SELECT 1
    FROM example_table t
    WHERE t.hour IS NULL
  )
) nh

结果

| NNH.NOT_NULL_HOURS+NH.NULL_HOURS |
------------------------------------
|                                3 |

这将花费大量精力来应对要求。一个更简单的选择是使用NVL,然后是两个简单的选择之一......要么:

  1. 用于TO_CHAR将非 NULL 值转换为数据类型 VARCHAR2并将值NVL转换NULL为 VARCHAR2'NULL'
  2. 只需使用NVL一个您知道将永远不会出现在结果集中的幻数(即由于表上的约束)。

查询 1

SELECT 
  COUNT(DISTINCT NVL(TO_CHAR(hour), 'NULL')) using_to_char_null
, COUNT(DISTINCT NVL(hour, -1)) using_magic_number
FROM example_table

结果

| USING_TO_CHAR_NULL | USING_MAGIC_NUMBER |
-------------------------------------------
|                  3 |                  3 |
于 2013-02-23T13:18:05.390 回答
1

安德烈斯的回答是完全满足要求的回答,除了COUNT

select count(distinct hour||' ') from hours;

我一直在为另一个目的寻找相同的东西(我可以使用任何东西),但在我看到这个之前,它对我来说似乎并不正确或有效,谢谢安德烈斯,一个如此简单但功能强大的解决方案。

于 2015-05-05T21:13:05.887 回答
0

我能得到的最接近指定标准的是:(SQL Fiddle

查询 1

SELECT COUNT(*)
FROM example_table t1
WHERE t1.ROWID IN (
  SELECT MAX(t2.ROWID)
  FROM example_table t2
  GROUP BY t2.hour
)

结果

| COUNT(*) |
------------
|        3 |

ROWID鉴于其他限制,不确定是否允许使用伪列,但它可以正常工作并优雅地处理NULL值。我认为 ROWID 不存在于 Oracle 之外,因此这可能与问题的精神背道而驰,但它至少符合列出的标准。

于 2013-02-23T22:21:53.323 回答
0

可能最简单的方法是使用DUMP

SELECT COUNT(DISTINCT DUMP(hour)) AS distinct_count
FROM hours;

输出:3

DBFiddle 演示

于 2017-11-27T19:34:41.153 回答
-1

啊……作业。不是这么简单吗?

SELECT COUNT(hour) 
  FROM hours

NULLS 不被计算在内。

知道了!没有正确阅读要求是我的坏事。

SELECT COUNT(DISTINCT COALESCE(hour,-1)) 
  FROM hours
于 2013-02-23T16:36:45.930 回答