SELECT 从具有可变数据的结果集中删除空列的语句
SELECT statement to remove empty columns from resultset with variable data
我有一个从 CSV 导入的 table 作为将数据收集到其他 table 的中间步骤。此 table 中的所有列都可以为空,但只要一列有数据,就是有效行。因此,可能存在包含空数据的完整行,这些行是无效的,无法考虑。
这是 table:
的一个(简化)示例
/* 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 │ │ ║
╚══════════╧══════════════════════════╧══════════╧═══════════════════════╧══════════╝
注意:请考虑以上 table/data 来自外部来源且不可修改,它也没有主键。它只是按 MySQL 中的原样导入。我不会得到 NULL
值,因为所有列都是 VARCHAR
.
我使用以下 SELECT 语句来获得相同的 table 但没有完整的空行:
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 │ │ ║
╚═══════╧══════════════════════════╧══════════╧═══════════════════════╧══════════╝
我需要做什么来删除所有行都为空的列? 在这个例子中,我需要上面的 table 但没有空列 title
.
由于此数据是动态的,因此有时可能会有另一列或多列为空,而我无法事先知道哪一列是空的。
您可以通过以下方式识别“空”列:
select
count(title),
count(description),
count(language),
count(url),
count(cagegory)
from imported_data
返回计数为 0
的列仅包含 null
个值。然后您可以删除相关的列,如果这是您想要的。
I won't get NULL values as all columns are 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;
以@GMB 答案为基础,我在准备好的语句中添加了一种动态方法来检查 where 子句中是否有任何已验证的字段为空,从而删除了完整的空行,如下所示:
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 where',
(
SELECT INSERT( GROUP_CONCAT('OR `', `COLUMN_NAME`, '` != \'\' ' SEPARATOR ' '), 1, 3, '')
FROM `information_schema`.`COLUMNS`
WHERE `TABLE_SCHEMA` = 'mydb'
AND `TABLE_NAME` = 'imported_data'
)
);
prepare stmt from @sql;
execute stmt;
deallocate prepare stmt;
我有一个从 CSV 导入的 table 作为将数据收集到其他 table 的中间步骤。此 table 中的所有列都可以为空,但只要一列有数据,就是有效行。因此,可能存在包含空数据的完整行,这些行是无效的,无法考虑。 这是 table:
的一个(简化)示例/* 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 │ │ ║
╚══════════╧══════════════════════════╧══════════╧═══════════════════════╧══════════╝
注意:请考虑以上 table/data 来自外部来源且不可修改,它也没有主键。它只是按 MySQL 中的原样导入。我不会得到 NULL
值,因为所有列都是 VARCHAR
.
我使用以下 SELECT 语句来获得相同的 table 但没有完整的空行:
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 │ │ ║
╚═══════╧══════════════════════════╧══════════╧═══════════════════════╧══════════╝
我需要做什么来删除所有行都为空的列? 在这个例子中,我需要上面的 table 但没有空列 title
.
由于此数据是动态的,因此有时可能会有另一列或多列为空,而我无法事先知道哪一列是空的。
您可以通过以下方式识别“空”列:
select
count(title),
count(description),
count(language),
count(url),
count(cagegory)
from imported_data
返回计数为 0
的列仅包含 null
个值。然后您可以删除相关的列,如果这是您想要的。
I won't get NULL values as all columns are 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;
以@GMB 答案为基础,我在准备好的语句中添加了一种动态方法来检查 where 子句中是否有任何已验证的字段为空,从而删除了完整的空行,如下所示:
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 where',
(
SELECT INSERT( GROUP_CONCAT('OR `', `COLUMN_NAME`, '` != \'\' ' SEPARATOR ' '), 1, 3, '')
FROM `information_schema`.`COLUMNS`
WHERE `TABLE_SCHEMA` = 'mydb'
AND `TABLE_NAME` = 'imported_data'
)
);
prepare stmt from @sql;
execute stmt;
deallocate prepare stmt;