SQL listagg 和 concat,删除重复项
SQL listagg and concat, remove duplicates
你好
我目前正在做一个关于 Tour de F运行ce 的学校项目,我必须使用 php、oracle 等创建一个网站,我正在努力这部分:
这是我正在使用的三个 table,每个都指定:
- 跑步者(键入跑步者 ID)
- 参赛者的国籍(键入参赛者 ID 和国际奥委会代码)
- 跑步者的参与(键入跑步者 ID 和年份)
我有这三个 table,我希望以某种格式将它们连接起来以使用 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;
为 Thorsten 点赞!
这是正确的查询(我只是更改了一些小问题,但效果非常好!):
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
你好
我目前正在做一个关于 Tour de F运行ce 的学校项目,我必须使用 php、oracle 等创建一个网站,我正在努力这部分:
这是我正在使用的三个 table,每个都指定:
- 跑步者(键入跑步者 ID)
- 参赛者的国籍(键入参赛者 ID 和国际奥委会代码)
- 跑步者的参与(键入跑步者 ID 和年份)
我有这三个 table,我希望以某种格式将它们连接起来以使用 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;
为 Thorsten 点赞!
这是正确的查询(我只是更改了一些小问题,但效果非常好!):
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