【问题标题】:How to join ids of two columns into one field and replaces those ids by their names如何将两列的 id 连接到一个字段中并用它们的名称替换这些 id
【发布时间】:2013-04-30 11:21:41
【问题描述】:

这些是我的桌子。

Step

stepid     name
a           place1
b           place2          
c           place3
d           place4
e           place5
f           place6


Stage

stageid     start        finish
1            a            b
2            b            c
3            c            d
4            d            e
5            e            f

Trip

tripid     stageid       
1            1            
1            2            
1            3            
1            4      
1            5  

我要实现这个查询结果

tripid     stageid       
1          place1,place2,place3,place4,place5,place6        

我知道如何将所有 id 放入一个字段,以及如何将 id 替换为其指定的名称。但是我不知道如何加入这两种解决方案。

这是我用来将 id 放入一个字段的 sql。

SELECT REPLACE(stageid,'''') as stages
FROM (SELECT SYS_CONNECT_BY_PATH(stageid,' ') stageid, level 
FROM trip
START WITH stageid = (select min(stageid) from trip)
CONNECT BY PRIOR stageid < stageid
ORDER BY level DESC) 
WHERE rownum = 1; 

start和finish是stepid的外键,trip table的stageid是Stage table的stageid的外键 我在 oracle developer ver 3.2 上工作。你能帮忙吗?

【问题讨论】:

  • 数据如何到达输出端?在我看来,tripid = 1 应该只给place1,place2,因为start=afinish=b
  • 好吧,对于tripid = 1,我得到1,2,3,4,5,我想用步骤表中的名称替换那些数字。在这种情况下,仅部分显示了行程表。事实上tripid 是某个其他表的外键。
  • 不是以您不应该用作列名的保留字开头吗?
  • 纯示例,无需展示实际的数据库结构。我希望它尽可能容易让“你”理解并可能提供帮助。

标签: sql oracle


【解决方案1】:

假设您可以访问LISTAGG,那么这是一个非常接近的选项:

SELECT tripid, stages || ',' || step.name
FROM (
  SELECT trip.tripid, 
    LISTAGG(step.name, ',') within group (order by stage.stageid) stages,
    MAX(stage.stageId) maxStageId
  FROM stage
    INNER JOIN step on stage.startstep = step.stepid
    INNER JOIN trip on stage.stageid = trip.stageid
  GROUP BY trip.tripid
) t INNER JOIN stage ON t.maxStageId = stage.stageId
    INNER JOIN step on stage.finishstep = step.stepid

SQL Fiddle Demo

基本上它使用 startstep 来构建列表,然后根据 max stage id 连接最后一个 finishstep。

【讨论】:

    【解决方案2】:

    试试这个,记住我将start重命名为startid

    SELECT tripid, REPLACE(stageid,'''') as stages
    FROM (
        SELECT tripid, SYS_CONNECT_BY_PATH(step.name,' ') stageid, level 
        FROM trip
        JOIN stage USING(stageid)
        JOIN step ON stage.startid=step.stepid
        START WITH stageid = (select min(stageid) from trip)
        CONNECT BY PRIOR stageid < stageid
        ORDER BY level DESC
      ) 
    WHERE rownum = 1; 
    

    它只输出开始步骤名称而不是 ID,如果您想获取行程中的所有地点,只需加入 start 和 end 并使用 distinct 可能会更容易

    如果有人有更好的想法,这里有一个小提琴: http://sqlfiddle.com/#!4/1d5d5/8

    【讨论】:

      【解决方案3】:

      我认为最简单的方法就是使用listagg() 来聚合字符串。将表连接在一起,然后聚合它们:

      select t.tripid,
             listagg(st.name, ',') within group (order by st.stepid)
      from trip t join
           stage s
           on t.stageid = s.stageid join
           step st
           on st.stepid in (s.start, s.finish)
      group by t.tripid
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-19
        • 2013-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-26
        相关资源
        最近更新 更多