【问题标题】:Count number of NULLs in a row计算一行中的 NULL 数
【发布时间】:2010-08-13 03:55:38
【问题描述】:

有没有办法获得一列指示一行中 NULL 字段的数量?这将在 SELECT 语句中。

例如:

Field1  Field2  Num_Null
-----------------------
NULL     "A"      1

更新:我想要这个查询,以便我可以根据给定书籍的关联销售量进行排序。因此,拥有 3 个附属机构的排序将高于拥有 2 个附属机构,无论是哪一个。我的数据库中大约有七个附属公司,而且还会增加。因此,任何需要指定每个 Affiliate 字段的查询都可能太长了

桌子:

Affiliates_Cache - 主键是 Affiliate_ISBN,具有各个附属公司的图书价格(如果不可用,则为 NULL)。 Affiliates_Cache 是我想计算 NULL 数量的地方

【问题讨论】:

  • 用你上次更新的一些进一步信息更新了我的答案:)

标签: sql mysql select null


【解决方案1】:

我不确定是否有更简洁的方法,但这应该可以:

SELECT Field1, Field2, ISNULL(Field1) + ISNULL(Field2) Num_Null
FROM   YourTable;

测试用例:

CREATE TABLE YourTable (Field1 varchar(10), Field2 varchar(10));

INSERT INTO YourTable VALUES (NULL, 'A');
INSERT INTO YourTable VALUES ('B', 'C');
INSERT INTO YourTable VALUES ('B', NULL);
INSERT INTO YourTable VALUES (NULL, NULL);

结果:

+--------+--------+----------+
| Field1 | Field2 | Num_Null |
+--------+--------+----------+
| NULL   | A      |        1 |
| B      | C      |        0 |
| B      | NULL   |        1 |
| NULL   | NULL   |        2 |
+--------+--------+----------+
4 rows in set (0.00 sec)

更新:关于更新后的问题:

如果您的表中的列看起来像 affiliate_1affiliate_2 等,这不是一个好主意,因为您会将数据与元数据混合。一般而言,推荐的解决方法是使用另一个依赖表来处理用户与附属机构的关系,如下例所示:

CREATE TABLE users (
   user_id int, 
   user_name varchar(100),
   PRIMARY KEY (user_id)
) ENGINE=INNODB;

CREATE TABLE users_affiliates (
   user_id int, 
   affiliate_name varchar(100),
   PRIMARY KEY (user_id, affiliate_name),
   FOREIGN KEY (user_id) REFERENCES users (user_id)
) ENGINE=INNODB;

然后按关联公司数量对users 表进行排序将如下所示:

SELECT    u.*, d_tb.num_aff
FROM      users
JOIN      (
             SELECT   user_id, COUNT(*) num_aff
             FROM     users_affiliates
             GROUP BY user_id
          ) d_tb ON (d_tb.user_id = u.user_id)
ORDER BY  d_tb.num_aff DESC;

优点很多,但最重要的是,它使上述查询易于编写,并且足够灵活,可以与任意数量的附属公司合作(不受您分配的列数的限制)。

【讨论】:

  • @OMG:如果你不知道更好,可能没有:)
  • 我会接受这个答案。但出于好奇,为什么 SQL 没有一些内置函数可以做到这一点?它有 .* 用于选择行
  • @babonk:很少有人要求进行计算。我从来不需要在正确规范化的数据上使用它。如果您有一年中 12 个月的 Sales_01 .. Sales_12 列,那么您可能只需要类似的东西 - 但最好对您的数据进行规范化。
  • 唯一真正的替代方法是使用一些 CASE 表达式,或 NVL() 等函数。他们没有提供足够的(任何?)好处;您的解决方案非常简洁。
  • Jonathan:我用它来根据一本书的附属机构数量进行排序。因此,拥有 3 个附属机构的排序将高于拥有 2 个附属机构,无论是哪一个。 [添加到问题]
【解决方案2】:

这个查询怎么样? (参考大牛给出的Test case。)

SELECT Field1, Field2, (2 - (COUNT(ALL Field1)+COUNT(ALL Field2)))  Num_Null
FROM   @YourTable
GROUP BY Field1, Field2

【讨论】:

  • 我需要计算大约 7 个字段,并且随着我添加更多的附属公司,字段的数量可能会更新,因此考虑到这一点,这个查询似乎太长了。 [更新问题]
【解决方案3】:

保持简单和标准:

SELECT Field1, Field2, 
       CASE WHEN Field1 IS NULL THEN 1 ELSE 0 END
       + CASE WHEN Field2 IS NULL THEN 1 ELSE 0 END
       AS Num__Null
  FROM YourTable;

完整的测试用例:

WITH YourTable (Field1, Field2)
     AS 
     (
      SELECT CAST(Field1 AS VARCHAR(10)), 
             CAST(Field2 AS VARCHAR(10))
        FROM (
              VALUES (NULL, 'A'),
                     ('B', 'C'),
                     ('B', NULL),
                     (NULL, NULL)
             ) AS YourTable (Field1, Field2)
     )
SELECT Field1, Field2, 
       CASE WHEN Field1 IS NULL THEN 1 ELSE 0 END
       + CASE WHEN Field2 IS NULL THEN 1 ELSE 0 END
       AS Num__Null
  FROM YourTable;

【讨论】:

  • 我需要计算大约 7 个字段,并且随着我添加更多的附属公司,字段的数量可能会更新,因此考虑到这一点,这个查询似乎太长了。 [更新问题]
猜你喜欢
  • 1970-01-01
  • 2015-10-05
  • 1970-01-01
  • 1970-01-01
  • 2022-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多