Как получить совпадающие данные из другой таблицы SQL для двух разных столбцов: Inner Join и / или Union?
У меня есть две таблицы в MS Access, которые отслеживают фасилитаторы классов и классы, которые они облегчают. Две таблицы структурированы следующим образом:
tbl_facilitators
facilID -> a unique autonumber to keep track of individual teachers
facilLname -> the Last name of the facilitator
facilFname -> the First name of the facilitator
tbl_facilitatorClasses
classID -> a unique autonumber to keep track of individual classes
className -> the name of the class (science, math, etc)
primeFacil -> the facilID from the first table of a teacher who is primary facilitator
secondFacil -> the facilID from the first table of another teacher who is backup facilitator
Я не могу понять, как написать Inner Join, который подтягивает результаты в этом формате:
Column 1: Class Name
Column 2: Primary Facilitator's Last Name
Column 3: Primary Facilitator's First Name
Column 4: Secondary Facilitator's Last Name
Column 5: Secondary Facilitator's First Name
Я могу подтянуть и получить правильные результаты, если я только запрашиваю первичного посредника самостоятельно или только сам вторичный посредник. Я не могу заставить их обоих работать, хотя.
Это мой рабочий Inner Join:
SELECT tbl_facilitatorClasses.className,
tbl_facilitators.facilLname, tbl_facilitators.facilFname
FROM tbl_facilitatorClasses
INNER JOIN tbl_facilitators
ON tbl_facilitatorClasses.primeFacil = tbl_facilitators.facilID;
В отчаянии я также попробовал Союз, но он не сработал, как я надеялся. Ваша помощь очень ценится. Я действительно изо всех сил пытаюсь добиться какого-либо прогресса в этой точке. Я не часто работаю с SQL.
РЕШЕНИЕ
Благодаря @philipxy я получил следующий запрос, который работал:
SELECT tblCLS.className,
tblP.facilLname, tblP.facilFname, tblS.facilLname, tblS.facilFname
FROM (tbl_facilitatorClasses AS tblCLS
INNER JOIN tbl_facilitators AS tblP
ON tblCLS.primeFacil=tblP.facilID)
INNER JOIN tbl_facilitators AS tblS
ON tblCLS.secondFacil=tblS.facilID;
При выполнении нескольких внутренних соединений в MS Access необходимо использовать круглые скобки... Как описано в этом другом посте.
3 ответа
Каждая базовая таблица имеет шаблон оператора, или предикат, параметризованный по именам столбцов, с помощью которого мы помещаем строку или пропускаем ее. Мы можем использовать сокращение для предиката, которое похоже на его объявление SQL.
// facilitator [facilID] is named [facilFname] [facilLname]
facilitator(facilID, facilLname, facilFname)
// class [classID] named [className] has prime [primeFacil] & backup [secondFacil]
class(classID, className, primeFacil, secondFacil)
Вставка строки в предикат дает утверждение, известное как предложение. Строки, которые составляют истинное предложение, входят в таблицу, а строки, которые составляют ложное предложение, не учитываются. (Таким образом, таблица устанавливает предложение каждой существующей строки и НЕ содержит предложение каждой отсутствующей строки.)
// facilitator f1 is named Jane Doe
facilitator(f1, 'Jane', 'Doe')
// class c1 named CSC101 has prime f1 & backup f8
class(c1, 'CSC101', f1, f8)
Но каждое значение выражения таблицы имеет предикат для каждого выражения. SQL разработан так, что если таблицы T
а также U
удерживайте строки (без дубликатов), где T (...) и U (...) (соответственно), затем:
T CROSS JOIN U
содержит строки, где T (...) И U (...)T INNER JOIN U ON
condition
содержит строки, в которых условие T(...) AND U(...) ANDT LEFT JOIN U ON
condition
содержит строки где (только для столбцов U1,...)
T (...) И U (...) И условие
ИЛИ Т (...)
И НЕ существует СУЩЕСТВУЮЩИХ значений для U1,... где [U(...) И условие ]
И U1 НУЛЬ И...T WHERE
condition
содержит строки, где T (...) И условиеT INTERSECT U
содержит строки, где T (...) И U (...)T UNION U
содержит строки, где T (...) ИЛИ U (...)T EXCEPT U
содержит строки, где T (...) И НЕ U (...)SELECT DISTINCT * FROM T
содержит строки, где T (...)SELECT DISTINCT
columns to keep
FROM T
содержит строки где
там СУЩЕСТВУЮТ значения для столбцов, чтобы отбросить где T (...)VALUES (C1, C2, ...)((
v1
,
v2
, ...), ...)
содержит строки где
С1 = v1 И С2 = v2 И... ИЛИ...
Также:
(...) IN T
означает Т (...)scalar
= T
означает Т (скаляр)- T (..., X,...) И X = Y означает T(..., Y, ...) И X = Y
Таким образом, для запроса мы находим способ выражения предиката для строк, которые нам нужны, на естественном языке, используя предикаты базовой таблицы, затем сокращенно с использованием предикатов базовой таблицы, затем в SQL, используя имена базовых таблиц (плюс условия, где это необходимо). Если нам нужно упомянуть таблицу дважды, мы даем ей псевдонимы.
// natural language
there EXISTS values for classID, primeFacil & secondFacil where
class [classID] named [className] has prime [primeFacil] & backup [secondFacil]
AND facilitator [primeFacil] is named [pf.facilFname] [pf.facilLname]
AND facilitator [secondFacil] is named [sf.facilFname] [sf.facilLname]
// shorthand
there EXISTS values for classID, primeFacil & secondFacil where
class(classID,className, primeFacil, secondFacil)
AND facilitator(pf.facilID, pf.facilLname, pf.facilFname)
AND pf.facilID = primeFacil
AND facilitator(sf.facilID, sf.facilLname, sf.facilFname)
AND sf.facilID = secondFacil
// table names & (MS Access) SQL
SELECT className, pf.facilLname, pf.facilFname, sf.facilLname, sf.facilFname
FROM (class JOIN facilitator AS pf ON pf.facilID = primeFacil)
JOIN facilitator AS sf ON sf.facilID = secondFacil
OUTER JOIN будет использоваться, когда у класса не всегда есть оба фасилитатора или что-то не всегда имеет все имена. (То есть, если столбец может иметь значение NULL.) Но вы не указали конкретные предикаты для своей базовой таблицы и запроса или бизнес-правила о том, когда все может быть NULL, поэтому я не принял NULL.
Просто сделайте дополнительное соединение для вспомогательного посредника (и, пожалуйста, используйте псевдонимы таблиц!):
SELECT fc.className, f1.facilLname, f2.facilFname
FROM tbl_facilitatorClasses fc
INNER JOIN tbl_facilitators f1 ON fc.primeFacil = f1.facilID
INNER JOIN tbl_facilitators f2 ON fc.secondFacil = f2.facilID;
Я бы сделал это, как описано выше, дважды присоединившись к таблице tbl_facilitators, но вы можете убедиться, что для каждого класса действительно требуется 2-й посредник, поскольку второе соединение должно быть внешним соединением. Действительно, было бы безопаснее предположить, что это не обязательное поле.