如何从所有列中选择不同的内容 - 将数据显示到出现的第一列

问题描述 投票:0回答:1

我有一个名为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 select mysql-workbench distinct
1个回答
0
投票

这里有一个想法,但这仅适用于 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;

演示小提琴

© www.soinside.com 2019 - 2024. All rights reserved.