#sql #oracle
#sql #Oracle
Вопрос:
Учитывая эти таблицы:
Employee(ssn, name, sex, address, salary, bdate, dno, superssn)
fk:superssn is ssn in Employee
fk:dno is dnumber in Department
Department(dnumber, dname, mgrssn, mgrstartdate)
fk:mgrssn is ssn in Employee
Dept_locations(dnumber, dlocation)
fk:dnumber is dnumber in Department
Project(pnumber, pname, plocation, dnum)
fk:dnum is dnumber in Department
Dependent(essn, dependent_name, sex, bdate, relationship)
fk: essn is ssn in Employee
Works_on(essn,pno,hours)
fk: essn is ssn in Employee; pno is pnumber in Project
Мне нужно повторно просмотреть название каждого отдела, а также название менеджера отдела для отделов, которые имеют два местоположения…
У меня пока есть этот запрос
SELECT D.dname, D.mgrssn
FROM department D, dept_locations DL
WHERE D.dnumber = dl.dnumber
Group by D.dname, D.mgrssn
Теперь я получаю три не дублирующихся отдела. Как мне ограничить это для отделов, которые имеют два местоположения?
Комментарии:
1. «очень быстро, пожалуйста» = домашнее задание?
2. спасибо за работу по редактированию, лол, когда я посмотрел на это, я увидел, насколько это было ужасно >_<
3. Вам следует попробовать использовать
GROUP BY
иHAVING
.4. Подумайте о том, что ваш запрос вернет сейчас (без
AND...
, удалите это). Для каждой сети подразделений с 3 местоположениями он вернет 3 строки. Для каждого отдела с 1 местоположением — 1 строка. Итак, вам нужно «сгруппировать по» отделу, чтобы собрать все строки отдела в одну строку (и посчитать их, если вам нужно). Это обычный способ обработки данных, которые разбиты более чем на одну строку.5. ооочень спасибо: D: D Я думаю, что могу получить это сейчас: D
Ответ №1:
SELECT D.dname, D.mgrssn
FROM Department D, Dept_locations DL
WHERE D.dnumber = DL.dnumber
GROUP BY D.dname, D.mgrssn
HAVING COUNT(*) >= 2 --- for 2 or more locations
и его лучше использовать INNER JOIN
(или просто JOIN
) вместо WHERE
для объединения связанных таблиц. Обратите внимание на отличие от предыдущего запроса. Оба будут возвращать одинаковые результаты :
SELECT D.dname, D.mgrssn
FROM Department D
JOIN Dept_locations DL
ON D.dnumber = DL.dnumber
GROUP BY D.dname, D.mgrssn
HAVING COUNT(*) >= 2
Если вы также хотите отобразить имя менеджера, вам также придется присоединиться к таблице Employee (и соответственно сгруппироваться):
SELECT D.dname
, D.mgrssn
, E.name
FROM Department D
JOIN Employee E
ON E.ssn = D.mgrssn
JOIN Dept_locations DL
ON D.dnumber = DL.dnumber
GROUP BY D.dname
, D.mgrssn
, E.name
HAVING COUNT(*) >= 2
Комментарии:
1. @Joel: В каждом отделе работает ровно один менеджер. Смотрите определения таблиц.
2. ОТДЕЛ имеет
mgrstartdate
, так что с исторической точки зрения существует более одного менеджера, связанного с ним. Кроме того, синтаксис ВНУТРЕННЕГО СОЕДИНЕНИЯ ANSI-89 и ANSI-92 выдает один и тот же план запроса; просто предпочтительнее использовать синтаксис ANSI-92 для ВНЕШНИХ соединений.3. @OMG: Договорились об объединениях. Однако это домашнее задание, так что это не вопрос лучшего плана или наилучшей практики, а игра в терминах учителя (которые должны совпадать с терминами наилучшей практики …)
4. @OMG: Что касается mgrstartdate, я предположил, что в каждом отделе хранится только один менеджер (текущий).
Ответ №2:
Ровно для двух местоположений:
SELECT d.name AS dept_name,
e.name AS mgr_name
FROM DEPARTMENT d
JOIN EMPLOYEE e ON e.ssn = d.mgrssn
WHERE EXISTS (SELECT NULL
FROM DEPT_LOCATIONS dl
WHERE dl.dnumber = d.dnumber
GROUP BY dl.dnumber
HAVING COUNT(*) = 2)
Для двух или более местоположений:
SELECT d.name AS dept_name,
e.name AS mgr_name
FROM DEPARTMENT d
JOIN EMPLOYEE e ON e.ssn = d.mgrssn
WHERE EXISTS (SELECT NULL
FROM DEPT_LOCATIONS dl
WHERE dl.dnumber = d.dnumber
GROUP BY dl.dnumber
HAVING COUNT(*) >= 2)
Имейте в виду
В DEPARTMENT
таблице есть mgrstartdate
, поэтому вам нужно свериться с ним — в двух приведенных мною примерах будут показаны все исторические менеджеры в дополнение к текущим менеджерам, потому что в mgrstartdate
таблице нет фильтрации.
Ответ №3:
select dname, name
from Department, Employee, Dept_locations
where mgrssn = ssn
and Department.dnumber = Dept_locations.dnumber
Комментарии:
1. у вас будет одна строка для каждого местоположения с дублирующимся отделом. если вам нужно объединить местоположения, используйте пользовательские функции, но я сомневаюсь, что ваш учитель рассказал вам, как их использовать. итак, это сработает.