简体   繁体   English

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

[英]How do I join the results of two queries in SQL Server?

This is my second SQL question today - I'm a bit of a newbie on the DBA stuff... 这是我今天的第二个SQL问题 - 我在DBA的东西上有点新手......

I am trying to join together a complex sql query to merge the data in about 12 tables into 1 single table. 我试图将一个复杂的SQL查询连接在一起,将大约12个表中的数据合并为1个单表。 Although there are one to many relationships in the database, I know what the maximum numbers of each are to be. 虽然数据库中有一对多关系,但我知道每个关系的最大数量。

So, I have (with stack overflow's help!) flatten out the first level of my database, and have a pair of queries, which must now be joined together: 所以,我有(使用堆栈溢出的帮助!)展平我的数据库的第一级,并有一对查询,现在必须连接在一起:

(abridged) (简略)

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'

Is it possible to name queries as aliases? 是否可以将查询命名为别名?
Or how else can I join these two queries so the output is like: 或者我怎么能加入这两个查询,所以输出如下:

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

** UPDATE ** The domain behind it is that an Assessment is carried out, on which both the school and the parent must report. **更新**背后的域名是进行评估,学校和家长必须在该评估中报告。 So the single row identifies an assessment which has both School and Parent values on it. 因此,单行标识评估,其中包含School和Parent值。

I'm using SQL Server 2005. 我正在使用SQL Server 2005。

Thanks! 谢谢!

* FURTHER UPDATE * This query seems to do the job... *进一步更新*此查询似乎可以完成...

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

FURTHER UPDATE (take 2!) ** (I'm not sure if I should reopen this as a new question??!) I got back to work today, to find my above 'solution' didn't quite solve the problem - it creates two rows for each assessment. 进一步更新(拿2!) ** (我不确定我是否应该重新打开这个作为一个新问题??!)我今天回到工作岗位,找到我上面的“解决方案”并没有完全解决问题 -它为每次评估创建两行。

So to recap, I have the following tables: 所以回顾一下,我有以下表格:

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

So for each student in the system there is exactly two Assessments - one with type 'School', and one with type 'Parent'. 因此,对于系统中的每个学生,只有两个评估 - 一个类型为“学校”,另一个类型为“父母”。

I want to create a single row which combines the assessments and concerns: 我想创建一个结合评估和关注点的行:

(pseudo columns:) (伪列:)

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

or from the sql above: 或者从上面的sql:

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

With only one row populated per student, which combines both assessments. 每个学生只填充一行,结合两种评估。 I have the structure for this working with the above SQL, but it returns two rows! 我有这个结构使用上面的SQL,但它返回两行! And I can't work out how to update this to only return one - any help gratefully received!! 我无法弄清楚如何更新这个只返回一个 - 感谢任何帮助!

Thanks as always! 一如既往地谢谢!

This can be done with just one query. 这可以通过一个查询完成。 The IN clause is just a fancy way of saying A.Type = 'School' OR A.Type = 'Parent' 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')

Make sure the field names you want are specified on the first query then UNION ALL the two queries; 确保在第一个查询中指定了所需的字段名称,然后 UNION ALL两个查询; if you want one set of results tagged on the end of the other. 如果你想在另一端的结尾标记一组结果。

Ignore my first answer, I'm taking rubbish as that won't get the result you want. 忽略我的第一个答案,我正在采取垃圾,因为这不会得到你想要的结果。 Sorry. 抱歉。

If you want the output to have repeated columns, where SIoC1 and PIoC1 are essentially the same but with a different name depending if the row is from a 'School' or 'Parent' then your result set will end up with NULLS all over it, eg (random data used as you don't provide sample data) 如果您希望输出具有重复的列,其中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.

If the data is stored in the same table, with the same field names use some other field to distinguish the rows, such as Type , and display that in the results. 如果数据存储在同一个表中,则使用相同的字段名称使用其他字段来区分行,例如Type ,并在结果中显示。

One query may be enough: 一个查询可能就足够了:

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

I think this query must return the same result as the one in your 'Further Update' section. 我认为此查询必须返回与“进一步更新”部分中的结果相同的结果。

The P.Type = ... conditions have been moved from WHERE to ON sections, so you can get the desired effect without having to resort to joining subselects. P.Type = ...条件已从WHERE移动到ON部分,因此您无需P.Type = ...加入子选择即可获得所需的效果。

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'

EDIT: Seems like grouping should help there. 编辑:似乎分组应该有帮助。 (I'm leaving my initial query so it's easier to see the necessary change for the updated requirement.) (我将离开初始查询,因此更容易看到更新要求的必要更改。)

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

You could select it all in one query and use the CASE statement to only populate the values where applicable 您可以在一个查询中选择所有内容,并使用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')

Edit: Preferably you would store the Type column so you could distinguish between the two types of data you wanted and then you would not have to repeat the columns as in the example above. 编辑:最好存储“类型”列,以便区分所需的两种类型的数据,然后不必像上面的示例那样重复列。 If you are creating a table then for it to conform to some form of normalization you wouldn't want to have repeated columns, however if you are using this select statement in a VIEW then it would be acceptable to do so. 如果要创建一个表,然后使其符合某种形式的规范化,则不希望重复列,但是如果在VIEW中使用此select语句,那么这样做是可以接受的。

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

Try this solution 试试这个解决方案

    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

The result column names must be the same (the alias used) and the same data types: 结果列名必须相同(使用的别名)和相同的数据类型:

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'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM