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

Posted

技术标签:

【中文标题】如何在 SQL Server 中加入两个查询的结果?【英文标题】:How do I join the results of two queries in SQL Server? 【发布时间】:2011-02-02 14:37:36 【问题描述】:

这是我今天的第二个 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 |

** 更新 ** 它背后的领域是进行评估,学校和家长都必须报告。因此,单行标识了包含学校和家长值的评估。

我使用的是 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 的结构,但它返回两行!而且我不知道如何更新它以只返回一个 - 任何帮助都非常感激!

一如既往的感谢!

【问题讨论】:

【参考方案1】:

这可以通过一个查询来完成。 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')

【讨论】:

不幸的是,这并没有让学校和家长的分数保持在同一条线上 - 不过感谢您的回复 @lainie:您表中的哪些字段用于将“学校”类型的结果与“家长”相关联? 评估 ID 链接学校和家长结果 - 我已经更新了我的问题,谢谢 @Iainie:我不明白这怎么可能。 A.Id 应该是 A.Type = 'School' 与 A.Type = 'Parent' 的不同值。 @Joe:你完全正确 - 这是一个学生 ID,与学校和家长相关联。道歉 - 不幸的是,混淆效果太好了......【参考方案2】:

确保在第一个查询中指定您想要的字段名称,然后在两个查询中指定 UNION ALL;如果您希望将一组结果标记在另一组的末尾。

忽略我的第一个答案,我正在接受垃圾,因为这不会得到你想要的结果。对不起。

如果您希望输出具有重复的列,其中 SIoC1PIoC1 本质上相同但名称不同,具体取决于该行是来自“学校”还是“父母”,那么您的结果集将结束到处都是NULL,例如(由于您不提供样本数据,使用随机数据)

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

【讨论】:

我已经用一些领域背景更新了我的问题 - 谢谢【参考方案3】:

一个查询可能就足够了:

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

【讨论】:

感谢您的回复 - 不幸的是,这并没有保留学校和家长栏。【参考方案4】:

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

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

【讨论】:

感谢您的回复,但这并不完全符合我的要求,因为它会为每个评估创建两行。【参考方案5】:

您可以在一个查询中全选并使用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 语句,那么这样做是可以接受的。

【讨论】:

【参考方案6】:

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

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'

【讨论】:

起初我给出了相同的答案,但后来意识到 OP 想要的最终结果集与两个查询的列不同。【参考方案7】:
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')

【讨论】:

【参考方案8】:

试试这个解决方案

    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

【讨论】:

以上是关于如何在 SQL Server 中加入两个查询的结果?的主要内容,如果未能解决你的问题,请参考以下文章

如何在查询中加入 MS-SQL 和 MySQL 表?

如何在sql的查询结果中加入序号

在sql server中加入两个视图

在 like 语句中加入 SQL Server 表

如何在 App Script 中加入两个表并将数据提取到大查询现有表中

如何在 SQL Server 中同时连接两个数据库?