繁体   English   中英

SQL listagg 和 concat,删除重复项

[英]SQL listagg and concat, remove duplicates

你好

我目前正在做一个关于环法自行车赛的学校项目,在那里我必须使用 php、oracle 等创建一个网站,我在这部分苦苦挣扎:


这是我正在使用的三个表,每个表都指定:

  1. 跑步者(键入跑步者 ID)
  2. 跑步者的国籍(以跑步者ID和国际奥委会代码为键)
  3. 跑步者的参与(键入跑步者 ID 和年份)

在此处输入图片说明


我有这三个表,我希望以某种格式连接它们以使用 php 处理它们,而不必以编程方式手动计算每个参与

val1data1|val2data1|val3data1;val1data2|val2data2|val3data2

它工作得很好,但仍然存在一个问题:如果跑步者多次参加,国籍将被参加人数重复,如果跑步者在多个国籍下参加比赛也是如此 这是发生了什么的一个例子.

在此处输入图片说明

这是我的 SQL 查询:

SELECT N_COUREUR, NOM, PRENOM, ANNEE_PREM, ANNEE_NAISSANCE,
        LISTAGG(".concatAll('|','annee','n_equipe','n_sponsor','n_dossard','jeune','valide').",';') WITHIN GROUP (ORDER BY N_COUREUR,NOM, PRENOM, ANNEE_PREM, ANNEE_NAISSANCE) participations, 
        LISTAGG(".concatAll('|','code_cio','ANNEE_DEBUT','ANNEE_FIN').",';') WITHIN GROUP (ORDER BY N_COUREUR,NOM, PRENOM, ANNEE_PREM, ANNEE_NAISSANCE) nationalites 
        FROM TDF_COUREUR 
        LEFT JOIN tdf_parti_coureur using(n_coureur) 
        LEFT JOIN tdf_app_nation using (n_coureur) 
        GROUP BY (N_COUREUR,NOM, PRENOM, ANNEE_PREM, ANNEE_NAISSANCE)
        ORDER BY N_COUREUR;

/*returns the correct concatenation for readability : (CONCAT(val1,CONCAT(val2,val3)) etc*/
function concatAll($separator, ...$arr){
            $string="";
            $count = count($arr);
            for($i = 0; $i<$count-1;$i++){
                $string .= "CONCAT(".$arr[$i].",CONCAT('$separator',";
            }
            $string .= $arr[$count-1];
            for($i = 0; $i<2*($count-1);$i++){
                $string .= ")";
            }
            return $string;
        }

我尝试将 CODE_CIO 或 ANNEE 添加到 WITHIN GROUP 中的任何一个,但无法解决,我是否错过了 WITHIN GROUP ?

一名跑者可以有多个国籍并参加多场比赛。 您加入了两个表,尽管特定的国籍与特定的种族无关。 因此,您正在生成不需要的笛卡尔积。 因此,问题是您正在加入不完全相关的实体。

连接所有涉及的表然后聚合膨胀的中间结果是一个常见的错误。 而是先聚合以获取您真正想要加入的实体。

您想要做的是向跑步者展示他们的种族列表和国籍列表。 创建这些列表,然后加入它们:

select
  c.n_coureur,
  c.nom,
  c.prenom,
  c.annee_prem,
  c.annee_naissance,
  pc.participations, 
  an.nationalites 
from tdf_coureur c
left join 
(
  select
    n_coureur,
    listagg(annee || '|' || n_equipe || '|' || n_sponsor || '|' || n_dossard || '|' || jeune || '|' || valide, ';') 
      within group (order by n_coureur, nom, prenom, annee_prem, annee_naissance) as participations
  from tdf_parti_coureur 
  group by n_coureur
) pc using(n_coureur)
left join 
(
  select
    n_coureur,
    listagg(code_cio || '|' || annee_debut || '|' || annee_fin, ';') 
      within group (order by n_coureur, nom, prenom, annee_prem, annee_naissance) as nationalites 
  from tdf_app_nation
  group by n_coureur
) an using(n_coureur)
order by c.n_coureur;

向托尔斯滕竖起大拇指!

这是正确的查询(我只是更改了一些小问题,但效果很好!):

select
    n_coureur,
    nom,
    prenom,
    annee_prem,
    annee_naissance,
    participations, 
    nationalites 
  from tdf_coureur c
  left join 
  (
    select
      n_coureur,
      listagg(annee || '|' || n_equipe || '|' || n_sponsor || '|' || n_dossard || '|' || jeune || '|' || valide, ';') 
        within group (order by n_coureur) as participations
    from tdf_parti_coureur 
    group by n_coureur
  ) pc using(n_coureur)
  left join 
  (
    select
      n_coureur,
      listagg(code_cio || '|' || annee_debut || '|' || annee_fin, ';') 
        within group (order by n_coureur) as nationalites 
    from tdf_app_nation
    group by n_coureur
  ) an using(n_coureur)
  order by n_coureur 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM