首页 > 解决方案 > SELECT 语句从具有可变数据的结果集中删除空列

问题描述

我有一个从 CSV 导入的表,作为将数据收集到其他表的中间步骤。此表中的所有列可能为空,但只要一列有数据,就是有效行。因此,可能存在包含空数据的完整行,这是无效的考虑。这是此类表的(简化)示例:

/* Table Structure */
CREATE TABLE `imported_data` (
  `title` varchar(45) DEFAULT NULL,
  `description` varchar(45) DEFAULT NULL,
  `language` varchar(45) DEFAULT NULL,
  `url` varchar(45) DEFAULT NULL,
  `category` varchar(45) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8

/* Table Data */
INSERT INTO imported_data (title, `description`, `language`, url, category) VALUES
('Le Titre', '', 'fra', '', '1'),
('', 'English Letters for Kids', '', 'https://anything.net', '2'),
('', '', '', '', ''),
('Master', 'The greatest master.', 'eng', 'http://www.master.com', '3'),
('', '', '', '', ''),
('', '', 'spa', '', '');


╔══════════╤══════════════════════════╤══════════╤═══════════════════════╤══════════╗
║ title    │ description              │ language │ url                   │ category ║
╠══════════╪══════════════════════════╪══════════╪═══════════════════════╪══════════╣
║          │                          │ fra      │                       │ 1        ║
╟──────────┼──────────────────────────┼──────────┼───────────────────────┼──────────╢
║          │ English letters for Kids │          │ https://anything.net  │ 2        ║
╟──────────┼──────────────────────────┼──────────┼───────────────────────┼──────────╢
║          │                          │          │                       │          ║
╟──────────┼──────────────────────────┼──────────┼───────────────────────┼──────────╢
║          │ The greatest master.     │ eng      │ http://www.master.com │ 3        ║
╟──────────┼──────────────────────────┼──────────┼───────────────────────┼──────────╢
║          │                          │          │                       │          ║
╟──────────┼──────────────────────────┼──────────┼───────────────────────┼──────────╢
║          │                          │ spa      │                       │          ║
╚══════════╧══════════════════════════╧══════════╧═══════════════════════╧══════════╝

注意:请注意上述表格/数据来自外部来源,不可修改,也没有主键。它只是在 MySQL 中导入。我不会得到NULL所有列的值VARCHAR

我使用以下 SELECT 语句来获取同一个表,但以这种方式没有完整的空行:

SELECT title, `description`, `language`, url, category
FROM imported_data2 WHERE
title != ''  OR `description` != ''  OR `language` != ''  OR url != ''  OR category != '' 

╔═══════╤══════════════════════════╤══════════╤═══════════════════════╤══════════╗
║ title │ description              │ language │ url                   │ category ║
╠═══════╪══════════════════════════╪══════════╪═══════════════════════╪══════════╣
║       │                          │ fra      │                       │ 1        ║
╟───────┼──────────────────────────┼──────────┼───────────────────────┼──────────╢
║       │ English letters for Kids │          │ https://anything.net  │ 2        ║
╟───────┼──────────────────────────┼──────────┼───────────────────────┼──────────╢
║       │ The greatest master.     │ eng      │ http://www.master.com │ 3        ║
╟───────┼──────────────────────────┼──────────┼───────────────────────┼──────────╢
║       │                          │ spa      │                       │          ║
╚═══════╧══════════════════════════╧══════════╧═══════════════════════╧══════════╝

我需要怎么做才能删除行全部为空的列?在这个例子中,我需要上面的表格,但没有空列title

由于这些数据是动态的,有时可能会有另一列或多列为空,我无法事先知道哪一列会这样。

标签: mysqlsqlselectdynamic-sqlsql-null

解决方案


您可以通过以下方式识别“空”列:

select 
    count(title), 
    count(description),
    count(language),
    count(url),
    count(cagegory)
from imported_data

返回计数的列0仅包含null值。然后,您可以删除相关列,如果这是您想要的。

我不会得到 NULL 值,因为所有列都是 VARCHAR。

字符串列可能肯定包含null值。如果您真的是指空字符串,而不是null,则使用nullif()

select 
    count(nullif(title, '')), 
    count(nullif(description, '')),
    count(nullif(language, '')),
    count(nullif(url, '')),
    count(nullif(category, ''))
from imported_data

如果你想要完全动态的东西,那么考虑构建使用准备好的语句:

set @sql = null;

select concat_ws(', ',
    case when count(nullif(title, ''))       > 0 then 'title'       end,
    case when count(nullif(description, '')) > 0 then 'description' end,
    case when count(nullif(language, ''))    > 0 then 'language'    end,
    case when count(nullif(url, ''))         > 0 then 'url'         end,
    case when count(nullif(category, ''))    > 0 then 'category'    end
) into @sql
from imported_data;

set @sql = concat('select ', @sql, ' from imported_data');  
prepare stmt from @sql;
execute stmt;
deallocate prepare stmt;

推荐阅读