Объединение двух операторов select вместе с помощью внешнего соединения

#sql #sql-server #join #subquery

#sql #sql-сервер #Присоединиться #подзапрос

Вопрос:

Мой запрос на SQL Server:

 select 
    s.learners_id, s.cv_student_id, 
    s.first_name   ' '   s.last_name student_name,
    p.program_name, dc.fulldate program_start_date, 
    sd.discount_value, dt.type_name
from
    fact_student_programs_t sp 
left join 
    object_sTATUSES_T os on os.object_statusid = sp.status_id
inner join 
    dim_programs_t p on p.programs_sk_id = sp.programs_sk_id
left join 
    dim_calendar dc on dc.datekey = sp.start_date_key
inner join 
    dim_students_t s on s.students_sk_id = sp.students_sk_id
outer join 
    (select 
         s.learners_id, sd.discount_value, dt.type_name
     from 
         fact_student_discountS_T sd 
     inner join 
         discount_types_t dt on dt.id = sd.discount_type_id
     inner join 
         dim_students_t s on s.students_sk_id = sd.students_sk_id
     where 
         sd.curr_in = 1) discounts on discounts.learners_id = s.learners_id
where 
    sp.curr_in = 1  
    and dc.fulldate is not null 
    and os.status_name in ('Active') 
    and s.learners_id in ('201328', '237744', '237817', '239826', '308486', '308961',
                          '308973', '309352', '311521', '312269', '312951',
                          '313254', '313289', '384170', '384224', '384228', 
                          '408911', '408912', '408936', '411293', '411308',
                          '411322', '411324', '411325', '411352', '411413',
                          '411417', '412865', '412923')
  

Я пытаюсь объединить эти два запроса, и у меня возникают проблемы. Является ли оператор внешнего соединения неправильным? Может кто-нибудь, пожалуйста, помочь мне исправить этот код?

РЕДАКТИРОВАТЬ: внешнее соединение здесь недопустимый синтаксис, поэтому я использую левое соединение. Запрос по-прежнему возвращает ошибку:

 Msg 4104, Level 16, State 1. The multi-part identifier "dt.type_name" could not be bound. Msg 4104, Level 16, State 1. The multi-part identifier "sd.discount_value" could not be bound. (Line 2)
  

Комментарии:

1. Пожалуйста, ознакомьтесь с допустимым синтаксисом SQL Server и визуальным представлением данных, которые он возвращает здесь: sqlservertutorial.net/sql-server-basics/sql-server-joins

Ответ №1:

Краткие сведения

outer join я полагаю, что недопустимо в SQL Server / t-sql. Это должно быть либо left outer join , right outer join либо full outer join .

В вашей ситуации, я подозреваю, вы хотите, чтобы это было left outer join .

Объяснение / более длинная версия

В левом и правом внешних соединениях «левый» и «правый» относятся к таблицам / etc буквально слева и справа от соединения (например, до и после объединения, соответственно).

  • В левом внешнем соединении он принимает все значения из таблицы слева (первая таблица) и любые совпадающие строки в таблице справа
  • При правильном внешнем соединении он принимает все значения из таблицы справа (вторая таблица) и любые совпадающие строки в таблице слева

Полное внешнее соединение получает все строки из обеих таблиц и сопоставляет их, когда это возможно.

Вот пример

 /* Data setup */
CREATE TABLE #T1 (T1_ID int);
CREATE TABLE #T2 (T2_ID int);
INSERT INTO #T1 (T1_ID) VALUES (1), (2);
INSERT INTO #T2 (T2_ID) VALUES (1), (3);

/* Example joins */
SELECT #T1.T1_ID, #T2.T2_ID
FROM #T1
LEFT OUTER JOIN #T2 ON #T1.T1_ID = #T2.T2_ID;

SELECT #T1.T1_ID, #T2.T2_ID
FROM #T1
RIGHT OUTER JOIN #T2 ON #T1.T1_ID = #T2.T2_ID;

SELECT #T1.T1_ID, #T2.T2_ID
FROM #T1
FULL OUTER JOIN #T2 ON #T1.T1_ID = #T2.T2_ID;

/* Results
-- LEFT OUTER JOIN
T1_ID   T2_ID
1       1
2       NULL

-- RIGHT OUTER JOIN
T1_ID   T2_ID
1       1
NULL    3

-- FULL OUTER JOIN
T1_ID   T2_ID
1       1
2       NULL
NULL    3
*/
  

Учитывая, что у вас есть WHERE s.learners_id in (...) в вашем предложении WHERE, это означает, что вам не нужны строки, в которых s.learners будет NULL .

  • Если у вас было правильное внешнее соединение, то требование WHERE эффективно превратит правильное внешнее соединение во внутреннее соединение (поскольку оно исключит все строки, где s.learners_id равно NULL).
  • Если бы у вас было полное внешнее соединение, то требование WHERE эффективно превратило бы полное внешнее соединение в левое внешнее соединение — по аналогичным логическим линиям.

Комментарии:

1. Спасибо за ответ. Да, левое соединение — это то, что мне нужно. Этот код не выполняется. Мое сообщение об ошибке: Msg 4104, Level 16, State 1. The multi-part identifier "dt.type_name" could not be bound. Msg 4104, Level 16, State 1. The multi-part identifier "sd.discount_value" could not be bound. (Line 2)

2. Поскольку таблица с псевдонимом sd является частью подзапроса, внешний запрос не может видеть саму таблицу; внешний запрос может использовать только подзапрос с псевдонимом as discounts . Попробуйте использовать discounts.type_name and discounts.discount_value во внешнем select .