使用组中表的数据

时间:2014-08-08 23:49:05

标签: sql oracle

名:

id,  first,     last

879  Scotty     Anderson
549  Melvin     Anderson
554  Freddy     Appleton
321  Grace      Appleton
112  Milton     Appleton
189  Jackson    Black
 99  Elizabeth  Black
298  Jordan     Frey

父母:

id,  student_id
549  879
321  554
112  554
 99  189
298  189

预期产出

(没有'学生:' /'家长:')

Student: Anderson, Scotty
 Parent: Anderson, Melvin

Student: Appleton, Freddy
 Parent: Appleton, Grace
 Parent: Appleton, Milton

Student: Black, Jackson
 Parent: Black, Elizabeth
 Parent: Frey, Jordan

使用上述数据,我如何实现预期的输出?

我目前使用与此类似的SQL来获取当前学生和姓名的列表。

select b.last, b.first
  from term a, names b
 where a.id = b.id(+)
 order by b.last

返回:

Anderson, Scotty
Appleton, Freddy
Black, Jackson

我的问题是如何获取parents表并添加到此查询以便它具有此输出:

Anderson, Scotty
Anderson, Melvin
Appleton, Freddy
Appleton, Grace
Appleton, Milton
Black, Jackson
Black, Elizabeth
Frey, Jordan

5 个答案:

答案 0 :(得分:1)

泛型SQL,mmmmm我希望有一个通用SQL:)

首先,您要停止使用Oracle独有的古董(+)连接语法

select b.last, b.first
  from term a
  LEFT OUTER JOIN names b ON a.id = b.id
  order by b.last

这是更通用的方式! (nb:你可以缩写为LEFT JOIN)

现在要连接(姓氏逗号空间名字),有些选项不是通用的

SQL Server / MySQL和其他支持CONCAT()

的人
select CONCAT(b.last , ', ', b.first)
  from term a
  LEFT OUTER JOIN names b ON a.id = b.id
  order by b.last

并非所有版本的Oracle或SQL Server都支持CONCAT() Oracle的concat()只需要2个参数; grrrrr

<强> ORACLE

select b.last || ', ' || b.first
  from term a
  LEFT OUTER JOIN names b ON a.id = b.id
  order by b.last

在这种形式下,Oracle通常会自动处理数据类型转换(我想,请检查日期/时间戳可能是其他人)

TSQL(Sybase,MS SQL Server)

select b.last + ', ' + b.first
  from term a
  LEFT OUTER JOIN names b ON a.id = b.id
  order by b.last

在这种形式中,如果不是字符串类型,则必须显式地将数据类型转换/转换为n | var | char以进行连接


有关连接名称的列表: 除了姓氏之外,您还需要一种方法来将家庭群体保留在一起,并加上区分学生和家长。由于您只需要一列名称,这表明您需要一列指向姓氏和名字的id。因此,对表TERM进行一些假设是你从中列出学生,然后追加与该组学生相关的父母,最后按所需顺序输出所需的列表。

select
      case when type = 1 then 'Student' else 'Parent' end as who
    , names.last || ', ' || names.first as Name
from (
      select
            STUDENT_ID     as name_id
          , STUDENT_ID     as family_id
          , 1              as TYPE
      from term
      union all
        select
              PARENTS.ID         as name_id
            , PARENTS.STUDENT_ID as family_id
            , 2                  as TYPE
        from PARENTS
        inner join term on PARENTS.STUDENT_ID = term.STUDENT_ID
    ) sq
inner join NAMES ON sq.name_id = NAMES.ID
order by
      names.last
    , sq.family_id
    , sq.type

请参阅:http://sqlfiddle.com/#!4/01804/6

答案 1 :(得分:1)

这样的查询中的想法是将数据分解为可帮助您解决问题的内容,然后根据需要将其重新组合在一起。在这种情况下,我将使用公共表表达式,这允许我将查询视为表,然后轻松地重新组合它们。

看看期望的结果,看起来我们希望让学生先出现,然后是他们的母亲(女士们先:-),然后是他们的父亲。那么,好吧,让我们弄清楚如何提取所需的数据。我们可以非常简单地获得学生及其相关数据:

select distinct p.student_id as student_id,
                n.first,
                n.last,
                0 as type
  from parents p
  inner join names n
  on n.id = p.student_id

type列的常量值为零,仅用于标识这是一名学生。 (你会在一分钟内看到原因)。

现在,由于我们没有任何性别信息可供使用,因此让母亲感到困难。但是,我们会使用我们拥有的名称。我们知道像Melvin,Milton和Jordan这样的名字是&#34; guy&#34;名。 (是的,我知道乔丹也可以成为一个女孩的名字。我的女儿有一个名叫乔丹的男教练,还有一个名叫乔丹的女队友。只要顺其自然 - 为了争论的目的,乔丹是个名字,&#39 ; K?&#39; K :-)。因此,我们会使用这些信息来帮助我们识别妈妈:

select p.student_id, n.first, n.last, 1 as type
  from parents p
  inner join names n
    on n.id = p.id
  where first not in ('Melvin', 'Milton', 'Jordan')

请注意,我们将值1分配给母亲的type列。

同样,我们会找到爸爸:

select p.student_id, n.first, n.last, 2 as type
  from parents p
  inner join names n
    on n.id = p.id
  where first in ('Melvin', 'Milton', 'Jordan')

这里我们为类型指定值为2。

好的 - 鉴于上述情况,我们只需要正确组合数据。但是,我们不想使用JOIN,因为我们希望名称从查询中一个接一个地吐出 - 而我们在SQL中执行的方式是使用UNION或{{ 1}}运算符。 (通常,您会想要使用UNION ALL,因为UNION ALL会检查结果集以确保没有重复项 - 在大型结果集需要的情况下,哦,或多或少FOREVER!)。因此,最终查询如下:

UNION

我们只取学生数据,然后是妈妈数据,然后是爸爸数据,然后根据学生ID从最高到最低排序(我只看了想要的结果,发现这应该是一个下降排序),然后按类型(导致学生(type = 0)成为第一,跟随他们的母亲(type = 1)然后他们的父亲(type = 2))。

SQLFiddle here

分享并享受。

答案 2 :(得分:0)

我会在SQL中这样做:

Select last +', '+ first as fullname from names;

答案 3 :(得分:0)

评论太长了。

你的问题没有意义。问题的简单答案是:

select last, first
from names;

但似乎不太可能是你想要的。

您的示例查询提到了表term。在问题的其他地方没有提到。请澄清问题或删除此问题并询问另一个问题。

答案 4 :(得分:0)

我想我明白了你要做的事情。我想你可以设置一个派生表然后查询它。设置如下:例如当学生id = id然后1其他0作为匹配或其他。然后按匹配查询派生表和分组。