如何在SQL Server中加入两个查询的结果?

时间:2011-02-02 14:37:36

标签: sql sql-server database

这是我今天的第二个SQL问题 - 我在DBA的东西上有点新手......

我正在尝试将一个复杂的SQL查询连接在一起,将大约12个表中的数据合并为1个单独的表。虽然数据库中有一对多关系,但我知道每个关系的最大数量。

所以,我(使用堆栈溢出的帮助!)展平了我的数据库的第一级,并且有一对查询,现在必须将它们连接在一起:

(删节)

SELECT 
  A.StudentId, C1.Topic AS SIoC1, C1.Level AS SIoCScore1
FROM Assessment A
  LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1
WHERE A.Type = 'School'

SELECT 
  A.StudentId, C1.Topic AS PIoC1, C1.Level AS PIoCScore1
FROM Assessment A
  LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1
WHERE A.Type = 'Parent'

是否可以将查询命名为别名?
或者我如何加入这两个查询,以便输出如下:

| A.Id | SIoC1 | SIoCScore1 | PIoC1 | PIoCScore1 |

**更新** 其背后的领域是进行评估,学校和家长必须在其上进行报告。因此,单行标识一个评估,其中包含School和Parent值。

我正在使用SQL Server 2005。

谢谢!

*进一步更新* 这个查询似乎可以完成这项工作......

SELECT PreConcerns.StudentId, TIoC1, TIoCScore1, PIoC1, PIoCScore1 
FROM
  Assessment PreConcerns
  LEFT OUTER JOIN
  (
    SELECT 
      P.StudentId, C1.Topic AS TIoC1, C1.Level AS TIoCScore1
    FROM Assessment  P
      LEFT JOIN Concern C1 ON P.Id = C1.Assessment_Id and C1.TopicNumber = 1
    WHERE P.Type = 'School'
  ) scons
  ON scons.StudentId= PreConcerns.StudentId
  LEFT OUTER JOIN
  (
    SELECT 
      P.StudentId, C1.Topic AS PIoC1, C1.Level AS PIoCScore1
    FROM Assessment  P
      LEFT JOIN Concern C1 ON P.Id = C1.Assessment_Id and C1.TopicNumber = 1
    WHERE P.Type = 'Parent'
  ) pcons
ON pcons.StudentId = PreConcerns.StudentId

进一步更新(拍2张!) ** (我不确定我是否应该重新开启这个问题?) 我今天回到工作岗位,发现上面的'解决方案'并没有完全解决问题 - 它为每次评估创建了两行。

回顾一下,我有以下表格:

Student (int:id, varchar(50):name)
Assessment (int:id, date:date, int:StudentId, )
Concern (int:id, int:assessment_id, varchar(20):topic, int:level)

因此,对于系统中的每个学生,只有两个评估 - 一个类型为“学校”,另一个类型为“父母”。

我想创建一个结合评估和关注点的行:

(伪列:)

| Assessment.StudentId | SchoolConcernTopic | SchoolConcernLevel | ParentConcernTopic | ParentConcernLevel |

或来自上面的sql:

| PreConcerns.StudentId | SIoC1 | SIoCScore1 | PIoC1 | PIoCScore1 |

每个学生只填充一行,结合两种评估。 我有这个结构使用上面的SQL,但它返回两行!我无法弄清楚如何更新这个只返回一个 - 任何帮助感激收到!!

一如既往地谢谢!

8 个答案:

答案 0 :(得分:4)

这可以通过一个查询来完成。 IN子句只是一种说A.Type = 'School' OR A.Type = 'Parent'

的奇特方式
SELECT 
  A.Id, C1.Topic AS PIoC1, C1.Level AS PIoCScore1
FROM Assessment A
  LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1
WHERE A.Type IN ('School','Parent')

答案 1 :(得分:2)

<击> 确保在第一个查询中指定了所需的字段名称,然后UNION ALL两个查询;如果你想在另一端的结尾标记一组结果。

忽略我的第一个答案,我正在服用垃圾,因为这不会得到你想要的结果。遗憾。

如果您希望输出包含重复列,SIoC1PIoC1基本相同,但名称不同,具体取决于该行是来自“学校”还是“家长”,那么结果集将以NULLS结束,例如(随机数据,因为您不提供样本数据)

| A.Id | SIoC1 | SIoCScore1 | PIoC1 | PIoCScore1 |
   1      A          10       NULL      NULL       -- Row type 'School'
   2     NULL       NULL       B        20         -- Row type 'Parent'   
etc. etc.

如果数据存储在同一个表中,则使用相同的字段名称使用其他字段来区分行,例如Type,并在结果中显示该行。

答案 2 :(得分:2)

一个查询可能就足够了:

SELECT 
  A.Id, A.Type, C1.Topic AS IoC1, C1.Level AS IoCScore1
FROM Assessment A
  LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1
WHERE A.Type IN ('School', 'Parent')

答案 3 :(得分:2)

我认为此查询必须返回与“进一步更新”部分中的结果相同的结果。

P.Type = ...条件已从WHERE移动到ON部分,因此您无需借助加入子选择即可获得所需的效果。

SELECT
  P.StudentId,
  CS.Topic AS TIoC1,
  CS.Level AS TIoCScore1,
  CP.Topic AS PIoC1,
  CP.Level AS PIoCScore1 
FROM
  Assessment P
    LEFT JOIN Concern CS ON P.Id = CS.Assessment_Id
      and CS.TopicNumber = 1 and P.Type = 'School'
    LEFT JOIN Concern CP ON P.Id = CP.Assessment_Id
      and CP.TopicNumber = 1 and P.Type = 'Parent'

编辑:似乎分组应该有帮助。 (我将离开我的初始查询,因此更容易看到更新要求的必要更改。)

SELECT
  P.StudentId,
  MAX(CS.Topic) AS TIoC1,
  MAX(CS.Level) AS TIoCScore1,
  MAX(CP.Topic) AS PIoC1,
  MAX(CP.Level) AS PIoCScore1 
FROM
  Assessment P
    LEFT JOIN Concern CS ON P.Id = CS.Assessment_Id
      and CS.TopicNumber = 1 and P.Type = 'School'
    LEFT JOIN Concern CP ON P.Id = CP.Assessment_Id
      and CP.TopicNumber = 1 and P.Type = 'Parent'
GROUP BY P.StudentId

答案 4 :(得分:1)

您可以在一个查询中选择所有内容,并使用CASE语句仅填充适用的值

SELECT
  A.Id, 
  CASE A.Type
    WHEN 'School' 
      THEN C1.Topic
    ELSE NULL
  END
  AS SIoC1, 
  CASE A.Type
    WHEN 'School' 
      THEN C1.Level
    ELSE NULL
  END
  AS SIoCScore1,
  CASE A.Type
    WHEN 'Parent' 
      THEN C1.Topic
    ELSE NULL
  END
  AS PIoC1, 
  CASE A.Type
    WHEN 'Parent' 
      THEN C1.Level
    ELSE NULL
  END AS PIoCScore1  
FROM Assessment A
  LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1
WHERE A.Type IN ('School', 'Parent')

编辑最好存储“类型”列,以便区分所需的两种类型的数据,然后就不必重复上述示例中的列。如果要创建一个表,然后使其符合某种形式的规范化,则不希望重复列,但是如果在VIEW中使用此select语句,那么这样做是可以接受的。

答案 5 :(得分:0)

结果列名必须相同(使用的别名)和相同的数据类型:

SELECT 
  A.Id, C1.Topic AS Topic, C1.Level AS Level
FROM Assessment A
  LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1
WHERE A.Type = 'School'

UNION

SELECT 
  A.Id, C1.Topic AS Topic, C1.Level AS Level
FROM Assessment A
  LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1
WHERE A.Type = 'Parent'

答案 6 :(得分:0)

SELECT
  A.Id, 
  CASE A.Type
    WHEN 'School' 
      THEN C1.Topic
    ELSE NULL
  END
  AS SIoC1, 
  CASE A.Type
    WHEN 'School' 
      THEN C1.Level
    ELSE NULL
  END
  AS SIoCScore1,
  CASE A.Type
    WHEN 'Parent' 
      THEN C1.Topic
    ELSE NULL
  END
  AS PIoC1, 
  CASE A.Type
    WHEN 'Parent' 
      THEN C1.Level
    ELSE NULL
  END AS PIoCScore1  
FROM Assessment A
  LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1
WHERE A.Type IN ('School', 'Parent')

答案 7 :(得分:0)

试试这个解决方案

    SELECT * INTO #School FROM
     (
      SELECT 
        A.StudentId, C1.Topic AS SIoC1, C1.Level AS SIoCScore1
      FROM Assessment A
      LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1
      WHERE A.Type = 'School'
       )school

    SELECT * INTO #Parent FROM
    (
     SELECT 
       A.StudentId, C1.Topic AS PIoC1, C1.Level AS PIoCScore1
      FROM Assessment A
      LEFT JOIN Concern C1 ON A.Id = Assessment_Id and C1.TopicNumber = 1
     WHERE A.Type = 'Parent'
    )parent

   SELECT 
   SL.StudentId
  ,SL.SIoC1
  ,SL.SIoCScore1
  ,PT.PIoC1
  ,PT.PIoCScore1 
 From #School SL
 LEFT JOIN #Parent PT ON PT.StudentId = SL.StudentId