Как мне объединить результаты двух запросов в SQL Server? - PullRequest
5 голосов
/ 02 февраля 2011

Это мой второй вопрос по SQL сегодня - я новичок в вопросах DBA ...

Я пытаюсь объединить сложный SQL-запрос, чтобы объединить данные из примерно 12 таблиц в одну таблицу. Хотя в базе данных есть отношения один ко многим, я знаю, каковы максимальные значения каждого из них.

Итак, я (с помощью переполнения стека!) Выровнял первый уровень моей базы данных и получил пару запросов, которые теперь должны быть объединены:

(в сокращенном виде)

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 ]

4 голосов
/ 02 февраля 2011

Это можно сделать всего одним запросом. Предложение 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')
2 голосов
/ 03 февраля 2011

Я думаю, что этот запрос должен возвращать тот же результат, что и в вашем разделе «Дальнейшее обновление».

Условия 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
2 голосов
/ 02 февраля 2011

Может быть достаточно одного запроса:

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')
2 голосов
/ 02 февраля 2011

Убедитесь, что имена полей, которые вы хотите, указаны в первом запросе, а затем UNION ALL в двух запросах;если вы хотите, чтобы один набор результатов был помечен в конце другого.

Не обращайте внимания на мой первый ответ, я беру мусор, поскольку он не даст желаемого результата.Извините.

Если вы хотите, чтобы выходные данные имели повторяющиеся столбцы, где SIoC1 и PIoC1, по сути, одинаковы, но с другим именем, в зависимости от того, является ли строка «School» или «Parent», тогдаваш результирующий набор будет иметь значение 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, и отобразите его в результатах.

1 голос
/ 02 февраля 2011

Вы можете выбрать все это в одном запросе и использовать оператор 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')

Редактировать: Желательно, чтобы выбудет хранить столбец Тип, чтобы вы могли различать два типа данных, которые вы хотели, и тогда вам не пришлось бы повторять столбцы, как в примере выше.Если вы создаете таблицу, то для того, чтобы она соответствовала какой-либо форме нормализации, вы не захотите иметь повторяющиеся столбцы, однако, если вы используете этот оператор select в VIEW, тогда это будет приемлемо.

0 голосов
/ 01 августа 2017

Попробуйте это решение

    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 голосов
/ 07 мая 2013
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 голосов
/ 02 февраля 2011

Имена столбцов результата должны быть одинаковыми (используемый псевдоним) и одинаковыми типами данных:

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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...