Oracle 11g:如何将 oracle 表与自身联合?

Posted

技术标签:

【中文标题】Oracle 11g:如何将 oracle 表与自身联合?【英文标题】:Oracle 11g: How to union an oracle table with itself? 【发布时间】:2012-11-06 19:04:31 【问题描述】:

我有一个如下所示的表格:

date          code                name    score         set
09/09/12     967873         Team A         24            1
09/09/12     967873         Team B         22            1
09/09/12     967873         Team A         21            2 
09/09/12     967873         Team B         16            2
02/04/12     965454         Team X         21            1
02/04/12     965454         Team Y         19            1
02/04/12     965454         Team X         21            2
02/04/12     965454         Team Y         19            2

你猜对了!这是一场排球比赛!但是,我希望我的输出在一行中。例如:

date           code               Teams                 Set-1    Set-2     Set-3
09/09/12      967873             Team A VS.Team B       24-22    21-16       -
and so on.... 

**Notice that the game could have a third set as well

我需要某种自我加入来将上述格式改进为更便于用户查看的格式...如果您需要更多详细信息,请告诉我。

谢谢,

【问题讨论】:

你如何确定哪个团队首先被列出? 只要分数与每组的球队匹配,球队的顺序无所谓 【参考方案1】:

查询可能如下所示:

with matches as (
   select "DATE", code, name,
      max(case when "SET" = 1 then score end) score_1,
      max(case when "SET" = 2 then score end) score_2,
      max(case when "SET" = 3 then score end) score_3,
      row_number() over(partition by "DATE", code order by name) team_no
    from games
    group by "DATE", code, name
)
select a."DATE", a.code, a.name || ' vs. ' || b.name teams,
  a.score_1 || '-' || b.score_1 set_1,
  a.score_2 || '-' || b.score_2 set_2,
  a.score_3 || '-' || b.score_3 set_3
from matches a
join matches b on a."DATE" = b."DATE" and a.code = b.code
where a.team_no = 1 and b.team_no = 2;

dateset 是相当不幸的列名。

查询分三步进行:

    汇总记录以为每支球队和每场比赛创建一行。在该过程中,分数被分配给 set_1、set_2、set_3 三列之一。 为每一行分配行号,从 1 开始为每个匹配。结果是一个团队被分配了 1,而另一个团队被分配了 2(列 team_no)。 生成的表连接到自身,左侧用于没有编号的团队。 1 和右侧的团队没有。 2 使用匹配(日期和代码)作为连接条件。结果是每场比赛的结果为一行,其中包含两支球队的名称和得分。

【讨论】:

非常感谢科多!它工作得很好:))也感谢您完成这个过程!现在我明白了【参考方案2】:

首先,将数据按"date", code, "set"LISTAGG 的球队和得分分组。然后在分数列上旋转结果。这是它的 SQL:

WITH grouped AS (
  SELECT
    "date", code, "set",
    LISTAGG(name,  ' VS. ') WITHIN GROUP (ORDER BY name) AS teams,
    LISTAGG(score, '-'    ) WITHIN GROUP (ORDER BY name) AS score
  FROM matches
  GROUP BY
    "date", code, "set"
)
,    pivoted AS (
  SELECT
    "date", code, teams,
    nvl("1", '-') AS set1,
    nvl("2", '-') AS set2,
    nvl("3", '-') AS set3
  FROM grouped
  PIVOT (
    MAX(score) FOR "set" IN (1, 2, 3)
  ) p
)
SELECT * FROM pivoted
;

请查看此查询at SQL Fiddle。

【讨论】:

【参考方案3】:

如果桌子的名称是 VOLLEYBALL,我会这样做 sg:

SELECT temp.date, temp.code, 
    temp.team1 || ' vs. ' || temp.team2 AS teams, 
    (SELECT v.score FROM volleyball v WHERE v.code = temp.code AND v.name = team1 AND v.set = 1) || '-' || 
        (SELECT v.score FROM volleyball v WHERE v.code = temp.code AND v.name = team2 AND v.set = 1) AS set1, 
    (SELECT v.score FROM volleyball v WHERE v.code = temp.code AND v.name = team1 AND v.set = 2) || '-' || 
        (SELECT v.score FROM volleyball v WHERE v.code = temp.code AND v.name = team2 AND v.set = 2) AS set2, 
    nvl((SELECT v.score FROM volleyball v WHERE v.code = temp.code AND v.name = team1 AND v.set = 3) || '-' || 
        (SELECT v.score FROM volleyball v WHERE v.code = temp.code AND v.name = team2 AND v.set = 3)
        , '-') AS set3 -- optional, if no results, then it will be a '-' 
FROM
    (SELECT v.date, v.code, 
        min(v.name) AS team1,  max(v.name) AS team2 
    FROM volleyball v 
    GROUP BY v.date, v.code) temp; 

这将产生一个单行摘要。

【讨论】:

您可能想要SELECT score FROM 而不是SELECT 1 FROM。而且你不需要nvl(XXX, '-')XXX 就足够了。 是的,对不起。我没有完成它。关于 nvl:我记得,NULL || '-' || NULLNULL,这就是我把它放在 nvl 函数中的原因。 不,NULL || '-' || NULL'-',至少在 Oracle 中。 好吧,确实如此。我手头没有数据库,但我现在可以检查它。【参考方案4】:

要在不需要连接的情况下返回所需的结果,请尝试:

select "date", 
       code, 
       min_name || ' VS. ' || max_name teams,
       sum(case when "set" = 1 and name = min_name then score end) || '-' || 
          sum(case when "set" = 1 and name = max_name then score end) "Set-1",
       sum(case when "set" = 2 and name = min_name then score end) || '-' || 
          sum(case when "set" = 2 and name = max_name then score end) "Set-2",
       sum(case when "set" = 3 and name = min_name then score end) || '-' || 
          sum(case when "set" = 3 and name = max_name then score end) "Set-3"
from (select g.*,
             min(name) over (partition by "date", code) min_name,
             max(name) over (partition by "date", code) max_name
      from games)
group by "date", code

【讨论】:

以上是关于Oracle 11g:如何将 oracle 表与自身联合?的主要内容,如果未能解决你的问题,请参考以下文章

从零开始学习Oracle数据库建表与简单查询

如何将 MySQL 中的表与 Oracle 中的表连接起来

如何将excel数据导入到数据库oracle11g

如何将 Laravel 8 连接到 oracle 11g 数据库?

如何安装Oracle11g

oracle11g中如何比较两个日期