我有一个名为egsmaster的表 mysql工作台版本:MySQL工作台是8.0.27
所以我将此列命名为 number_id、产品、法语、德语、英语、意大利语 这种语言是产品的类别,所以我想从所有列中获取不同记录的返回列表,
首先获得法语的不同记录,然后是德语、英语和意大利语,所以我这样做了
这是我的询问
SELECT
COALESCE(category_french, '') AS french,
COALESCE(category_german, '') AS german,
COALESCE(category_english, '') AS english,
COALESCE(category_italian, '') AS italian
FROM (
SELECT DISTINCT
category_french,
category_german,
category_english,
category_italian
FROM
egsmaster
) AS t
WHERE
COALESCE(category_french, '') <> ''
OR COALESCE(category_german, '') <> ''
OR COALESCE(category_english, '') <> ''
OR COALESCE(category_italian, '') <> ''
AND (category_french IS NOT NULL
OR category_german IS NOT NULL
OR category_english IS NOT NULL
OR category_italian IS NOT NULL);
如果我运行这个查询,我将得到这样的结果集
french | german | english | italian
tree | tall | hall | itall
| aaa | |
| | fff |
| | | yyyy
| bds | bgs | itall
trek | tall | |
| | | tr
trq | sss | ggg | tret
12 | re | a12 | ass
arrow | irrow | |
back | | | bock
sap | | | Sip
| Itat | itaa |
| | Iasd | kaka
| | | sa,p
| | | lasut
但我想要的是有一个干净的结果集,这样如果我将其导出到 Excel 中,它将显示如下
french | german | english | italian |
tree aaa fff yyyy
trek bds lasd tr
trq itat sa,p
12 lasut
arrow
back
sap
在一行中,如果有多列包含数据,则出现该数据的第一列必须是 唯一需要返回的
不管 id 我只需要做的是从所有语言列中获取不同的数据
这里有一个想法,但这仅适用于 MySQL v8+。
我将使用
Common Table Expression (cte)
和 ROW_NUMBER()
作为主函数,并使用 IFNULL()
作为可选函数 - 仅当您的数据同时包含 NULL
和 ''
作为空值时。
首先,我们将使用您的示例查询作为基础并将其包装在第一个
cte
中,如下所示:
/*1st part*/
WITH cat_tbl AS (
SELECT DISTINCT
category_french,
category_german,
category_english,
category_italian
FROM
egsmaster
)
现在我们在第二个
cat_tbl
中使用cte
来生成ROW_NUMBER()
:
/*1st part*/..,
/*2nd part*/
cat_tblrn AS (
SELECT ROW_NUMBER() OVER () AS Rn, cat_tbl.*
FROM cat_tbl)
现在我们有了行号作为下一个行号的参考,我们将为每个语言列单独生成该行号。根据您的数据样本,
category_french
是要列出的第一列。这是一个cte
:
/*1st part*/..,
/*2nd part*/..,
/*3rd part - 1*/
cat_fr AS (
SELECT ROW_NUMBER() OVER (ORDER BY Rn) AS FrRn,
category_french
FROM cat_tblrn
WHERE IFNULL(category_french,'')!=''),
cat_fr
是 cte
名称,条件是 category_french
列值不为空(或 NULL
)。
注意:正如我提到的,如果您不确定空数据值是
NULL
还是''
,那么您可以像在查询中一样使用IFNULL()
函数。但是,如果空值始终为 NULL
,那么您可以将 IFNULL(column_name,'')!=''
部分更改为 column_name IS NOT NULL
。或者,如果空列始终 ''
那么只需 column_name != ''
。
下一个
cte
是为了category_german
:
/*1st part*/..,
/*2nd part*/..,
/*3rd part - 2*/
cat_fr AS (
SELECT ROW_NUMBER() OVER (ORDER BY Rn) AS FrRn,
category_french
FROM cat_tblrn
WHERE IFNULL(category_french,'')!=''),
cat_gr AS (
SELECT ROW_NUMBER() OVER (ORDER BY Rn) AS GrRn,
category_german
FROM cat_tblrn
WHERE IFNULL(category_french,'')='' AND IFNULL(category_german,'')!='' )
这个
cat_gr
和 cat_fr
cte 之间的区别显然是 SELECT
中的列将是 category_german
,并在 IFNULL(category_french,'')=''
中添加一个 WHERE
,以指示 cat_gr
仅应在 category_french
时返回值是空的。其余的 cte
将具有相同的 WHERE
,并对前面的每个列值进行额外检查,最终结果如下:
/*1st part*/..,
/*2nd part*/..,
/*3rd part - full*/
cat_fr AS (
SELECT ROW_NUMBER() OVER (ORDER BY Rn) AS FrRn,
category_french
FROM cat_tblrn
WHERE IFNULL(category_french,'')!=''),
cat_gr AS (
SELECT ROW_NUMBER() OVER (ORDER BY Rn) AS GrRn,
category_german
FROM cat_tblrn
WHERE IFNULL(category_french,'')='' AND IFNULL(category_german,'')!='' ),
cat_en AS (
SELECT ROW_NUMBER() OVER (ORDER BY Rn) AS EnRn,
category_english
FROM cat_tblrn
WHERE IFNULL(category_french,'')='' AND IFNULL(category_german,'')=''
AND IFNULL(category_english,'')!=''),
cat_ita AS (
SELECT ROW_NUMBER() OVER (ORDER BY Rn) AS ItaRn,
category_italian
FROM cat_tblrn
WHERE IFNULL(category_french,'')='' AND IFNULL(category_german,'')=''
AND IFNULL(category_english,'')='' AND IFNULL(category_italian,'')!='')
现在我们已经准备好了所有的
cte
,我们可以简单地使用LEFT JOIN
来获得想要的结果:
/*1st part*/..,
/*2nd part*/..,
/*3rd part*/..,
/*final part*/
SELECT category_french,
category_german,
category_english,
category_italian
FROM cat_fr
LEFT JOIN cat_gr ON FrRn=GrRn
LEFT JOIN cat_en ON FrRn=EnRn
LEFT JOIN cat_ita ON FrRn=ItaRn;