[英]SQL listagg and concat, remove duplicates
你好
我目前正在做一个关于环法自行车赛的学校项目,在那里我必须使用 php、oracle 等创建一个网站,我在这部分苦苦挣扎:
这是我正在使用的三个表,每个表都指定:
我有这三个表,我希望以某种格式连接它们以使用 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.