SQL Внутреннее объединение
У меня есть проблема с моим внутренним разделением соединения ниже. Из моего оракула мне не хватает правильных скобок, когда я уже закрыл его. Мне нужно получить имена пациентов, которые собрали все предметы.
Select P.name
From ((((Select Patientid From Patient) As P
Inner Join (Select Accountno, Patientid From Account) As A1
on P.PatientID = A1.PatientID)
Inner Join (Select Accountno, Itemno From AccountType) As Al
On A1.Accountno = Al.Accountno)
Inner Join (Select Itemno From Item) As I
On Al.Itemno = I.Itemno)
Group By Al.Itemno
Having Count(*) >= (Select Count(*) FROM AccountType);
2 ответа
Вот более простой подход, который, я считаю, по сути эквивалентен:
select a.name
from Patient a
inner join Account b on a.PatientID = b.PatientID
inner join AccountType c on b.Accountno = c.Accountno
inner join Item d on c.Itemno = d.Itemno
group by c.Accountno, a.name
having Count(*) >= (Select Count(*) FROM AccountType);
Этот подход немного проще. Это дает дополнительное преимущество, заключающееся в большей вероятности использования индексов в таблицах - если вы выполняете соединения между тем, что по сути является "таблицами соединений" в памяти, вы не получаете преимущества от индексов, которые существуют для физических таблиц в объем памяти.
Я также обычно называю псевдонимы таблиц последовательными буквами - "a", "b", "c", "d", как вы можете видеть. Я обнаружил, что когда я пишу сложные запросы, мне легче следовать за ними. "a" - первая таблица в соединении, "b" - вторая и т. д.
Похоже, вы просто хотите
SELECT p.name
FROM patient p
INNER JOIN account a ON (a.patientID = p.patientID)
INNER JOIN accountType accTyp ON (accTyp.accountNo = a.accountNo)
INNER JOIN item i ON (i.itemNo = accTyp.itemNo)
GROUP BY accTyp.itemNo
HAVING COUNT(*) = (SELECT COUNT(*)
FROM accountType);
Обратите внимание, что наличие псевдонима A1 и псевдонима Al довольно запутанно. Вы хотите выбрать более значимые и более отличительные псевдонимы.