开发者

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

开发者 https://www.devze.com 2023-02-08 17:04 出处:网络
This is my second SQL question today - I\'m a bit of a newbie on the DBA stuff... I am trying to join together a complex sql query to merge the data in about 12 tables into 1 single table.Although th

This is my second SQL question today - I'm a bit of a newbie on the DBA stuff...

I am trying to join together a complex sql query to merge the data in about 12 tables into 1 single table. 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.

I'm using 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.

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 | SchoolConc开发者_如何学JAVAernLevel | ParentConcernTopic | ParentConcernLevel |

or from the sql above:

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

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; 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, e.g. (random data used as you don't provide sample data)

| 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.


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.

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

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.


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'


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
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号