2011-02-02 133 views
5

这是我今天的第二个SQL问题 - 我是一个DBA的东西新手...如何在SQL Server中连接两个查询的结果?

我想联合在一起一个复杂的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 | 

**更新** 其背后的域是一个评估进行,在这两个学校和家长必须报告。所以单行标识了一个既有学校价值又有父母价值的评估。

我正在使用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的结构,但它返回两行!而我无法解决如何更新这个只返回一个 - 任何帮助感激地收到!

一如既往的感谢!

回答

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,和显示在结果中。

+0

我已经更新了我的问题的一些领域背景 - 谢谢 – laura 2011-02-02 14:56:21

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') 
+0

感谢您的回复 - 不幸的是,这并没有保留学校和父母的专栏。 – laura 2011-02-02 14:51:27

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') 
+0

不幸的是,这并未将学校和家长的分数保持在同一行 - 感谢回复 – laura 2011-02-02 14:52:00

+0

@lainie:表中的哪些字段用于将“学校”类型的结果与“父母”的结果相关联? – Tony 2011-02-02 14:54:02

+0

评估ID链接学校和家长的结果 - 我已经更新了我的问题,谢谢 – laura 2011-02-02 14:55:47

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' 
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语句,那么这样做是可以接受的。

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 
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') 
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