Помогите с SQL
18 повідомлень
#16 років тому
Есть таблица актеров пусть наз-ся akter со столбцами (id,fio,adres), и у каждого актера есть характеристики например : владение музыкальными иструментами.
Таблица для подобных характеристик иммет поля (id, name), пусть для "владения муз. инструментами" таблица будет наз-ся tb1.
Для хранения таких характеристик для каждого актера есть еще таблицы с полями (id,harID - id записи из таблицы характеристик, akterID - id актера).
Пусть для "владения муз. инструментами" такая таблица имеет имя tb1_svaz.
Вопрос такой: как сделать выборку чтобы показались все актеры не владеющии 2 определенными характеристиками. Например актеры не играющие на гитаре и скрипке ?
заранее спасибо. надеюсь ясно объяснил
18 повідомлень
#16 років тому
Цитата ("hobl"):Т.е. tb1 содержит названия инструментов? а tb1_svaz соотвествие между музыкантом и инструментом?
В итоге имеем: таблица Музыкант(Идентификатор музыканта, Имя), Инструмент(Идентификатор инструмента, Название), Соответствие(Идентификатор, Идентификатор музыканта, Идентификатор инструмента). Поставить запрос: найти музыкантов, которые не владеют двумя заданными инструментами?
Так это дет. сад
Напиши пожалуйста SQL запрос
1895 повідомлень
#16 років тому
select актери.*
from актери, интсрументы
where (актеры.id = инуструменты.id_актера) and (инстурменты.id not in (id_перового_иснтурумента, id_второго_иснтурумента))
это же элементарно)
П.С. Также можно на джойнах это реализовать, только я их не люблю особенно)
18 повідомлень
#16 років тому
Цитата ("MMM_Corp"):select актери.*
from актери, интсрументы
where (актеры.id = инуструменты.id_актера) and (инстурменты.id not in (id_перового_иснтурумента, id_второго_иснтурумента))
это же элементарно)
П.С. Также можно на джойнах это реализовать, только я их не люблю особенно)
спасибо.
1090 повідомлень
#16 років тому
Цитата ("MMM_Corp"):select актери.*
from актери, интсрументы
where (актеры.id = инуструменты.id_актера) and (инстурменты.id not in (id_перового_иснтурумента, id_второго_иснтурумента))
Мда... Давно такого не видел.
Автор, не делай так, используй джойны.
Только уточни СУБД.
3240 повідомлень
#16 років тому
Вариант MMM_Corp не будет корректно работать, если в базе данных могут быть актеры, не играющие ни на одном инструменте.Если такое возможно, тогда вот корректный запрос:
SELECT *
FROM akter
WHERE id NOT IN (
SELECT akterID
FROM tb1_svaz
INNER JOIN tb1 ON tb1.id = tb1_svaz.harID
WHERE tb1.name IN ('гитара', 'скрипка')
)
Или, если известны ID инструментов, то запрос упрощается:
SELECT *
FROM akter
WHERE id NOT IN (
SELECT akterID
FROM tb1_svaz
WHERE tb1_svaz.harID IN ('гитара_id', 'скрипка_id')
)
То есть, сначала во вложенном подзапросе получаем список актеров, которые играют на "запрещенных" инструментах, а затем выводим остальных актеров не из их числа.
P.S. Пожалуйста сразу приучайте себя к хорошему стилю, и называйте таблицы и поля корректными наименованиями, например actor, instrument, для связи - actor_instrument, и т.д.
18 повідомлень
#16 років тому
Цитата ("alibek"):Цитата ("MMM_Corp"):select актери.*
from актери, интсрументы
where (актеры.id = инуструменты.id_актера) and (инстурменты.id not in (id_перового_иснтурумента, id_второго_иснтурумента))
Мда... Давно такого не видел.
Автор, не делай так, используй джойны.
Только уточни СУБД.
субд MYSQL
18 повідомлень
#16 років тому
Select актери.* from актери, интсрументы
where (актеры.id = инуструменты.id_актера) and (инстурменты.id not in (id_перового_иснтурумента, id_второго_иснтурумента))
так попробовал, не совсем верно получилось. так как если актер играет например на гитаре, скрипке, барабанах по его все равно показывает. так как барабаны не входят в условие
1895 повідомлень
#16 років тому
Цитата ("alibek"):Цитата ("MMM_Corp"):select актери.*
from актери, интсрументы
where (актеры.id = инуструменты.id_актера) and (инстурменты.id not in (id_перового_иснтурумента, id_второго_иснтурумента))
Мда... Давно такого не видел.
Автор, не делай так, используй джойны.
Только уточни СУБД.
Я дал общый совет, согласно стандартов SQL-92, в которые операция join может иметь свои специфики работы для различных СУБД, это значит что мой вариант на 99% универсален для всех SQL-92 совместимых СУБД, заметьте автор не указал СУБД.
Цитата:
Вариант MMM_Corp не будет корректно работать, если в базе данных могут быть актеры, не играющие ни на одном инструменте.
Это еще почему? Я видь указал :
where (актеры.id = инуструменты.id_актера), что указивает на явную связь актер-инстуремнт на котором он играет, что исключает попадание сюда актеров которые ни на чем не играют!
18 повідомлень
#16 років тому
Цитата ("tvv"):Вариант MMM_Corp не будет корректно работать, если в базе данных могут быть актеры, не играющие ни на одном инструменте.
Если такое возможно, тогда вот корректный запрос:SELECT *
FROM akter
WHERE id NOT IN (
SELECT akterID
FROM tb1_svaz
INNER JOIN tb1 ON tb1.id = tb1_svaz.harID
WHERE tb1.name IN ('гитара', 'скрипка')
)
Или, если известны ID инструментов, то запрос упрощается:SELECT *
FROM akter
WHERE id NOT IN (
SELECT akterID
FROM tb1_svaz
WHERE tb1_svaz.harID IN ('гитара_id', 'скрипка_id')
)
То есть, сначала во вложенном подзапросе получаем список актеров, которые играют на "запрещенных" инструментах, а затем выводим остальных актеров не из их числа.
P.S. Пожалуйста сразу приучайте себя к хорошему стилю, и называйте таблицы и поля корректными наименованиями, например actor, instrument, для связи - actor_instrument, и т.д.
Спасибо. Сейчас попробую. Названия таблиц не такие. Они слишком длинные поэтому я их тут сократил
1895 повідомлень
#16 років тому
Укажите СУБД, сделайте SQL-дамп, потом обсудим. П.С. Больше на меня не ссылайтесь, работы полно, да и все равно на моем примере идея разворачивается

3240 повідомлень
#16 років тому
Цитата ("MMM_Corp"):Это еще почему? Я видь указал :where (актеры.id = инуструменты.id_актера), что указивает на явную связь актер-инстуремнт на котором он играет, что исключает попадание сюда актеров которые ни на чем не играют!
Вот именно, исключает.
А условие было такое, что нужно вывести всех актеров, которые не играют на гитаре и скрипке.
Если актер не играет ни на каком инструменте, то это значит, что он в том числе не играет на гитаре и скрипке, и по условию его тоже нужно выводить, не так ли?
Вы же вывели актеров, которые обязательно играют на чем-то, что не гитара и не скрипта, причем если актер играет еще и на контрабасе и пианино, он выведется дважды (в Вашем случае DISTINCT нужно еще указать, или GROUP BY).
Цитата ("alibek"):
tvv, можно куда проще, через left join.
Я не думаю что через LEFT JOIN проще (учитывая, что нужно помнить о группировке по актеру).
Да и по производительности спорно какой вариант лучше, нужно делать замеры на реальных наборах данных.
Вот напишите Ваш вариант запроса, подумаем, обсудим.
120 повідомлень
#16 років тому
Цитата ("MMM_Corp"):П.С. Также можно на джойнах это реализовать, только я их не люблю особенно)
from a, b where a.field = b.field
Это тоже джойн, только неявный
120 повідомлень
#16 років тому
Таблицы
CREATE TABLE instruments
(id NUMBER NOT NULL,
name VARCHAR2(100))
CREATE TABLE instruments
(id NUMBER NOT NULL,
name VARCHAR2(100))
CREATE TABLE links
(id_artist NUMBER,
id_instrument NUMBER)
Данные
INSERT INTO artists VALUES (1,'Иванов')
INSERT INTO artists VALUES (2,'Петров')
INSERT INTO artists VALUES (3,'Сидоров')
INSERT INTO artists VALUES (4,'Федоров')
INSERT INTO artists VALUES (5,'Сергеев')
INSERT INTO artists VALUES (6,'Романов')
INSERT INTO instruments VALUES (1,'Гитара')
INSERT INTO instruments VALUES (2,'Скрипка')
INSERT INTO instruments VALUES (3,'Фортепиано')
INSERT INTO instruments VALUES (4,'Арфа')
INSERT INTO instruments VALUES (5,'Труба')
INSERT INTO links VALUES (1, 2)
INSERT INTO links VALUES (1,3)
INSERT INTO links VALUES (2,3)
INSERT INTO links VALUES (1,4)
INSERT INTO links VALUES (2,4)
INSERT INTO links VALUES (3,5)
Ну и собственно запрос:
SELECT
a.id, a.name,
i.id, i.name
FROM artists a
LEFT JOIN links l ON l.id_artist = a.id
LEFT JOIN instruments i ON l.id_instrument = i.id
WHERE i.name NOT IN ('Фортепиано', 'Арфа') or i.name IS NULL
322 повідомлення
#16 років тому
То, что вы назвали джоином, то это не джоин. В оракле может быть это джоином
120 повідомлень
#16 років тому
Если убрать секцию WHERE, то получим полный список:Цитата:
1 Иванов 2 Скрипка
2 Петров 3 Фортепиано
1 Иванов 3 Фортепиано
2 Петров 4 Арфа
1 Иванов 4 Арфа
3 Сидоров 5 Труба
4 Федоров
5 Сергеев
6 Романов
А если с WHERE, то получим искомый результат:
Цитата:
1 Иванов 2 Скрипка
3 Сидоров 5 Труба
4 Федоров
5 Сергеев
6 Романов
18 повідомлень
#16 років тому
Цитата ("korstin"):Таблицы
CREATE TABLE instruments
(id NUMBER NOT NULL,
name VARCHAR2(100))
CREATE TABLE instruments
(id NUMBER NOT NULL,
name VARCHAR2(100))
CREATE TABLE links
(id_artist NUMBER,
id_instrument NUMBER)
Данные
INSERT INTO artists VALUES (1,'Иванов')
INSERT INTO artists VALUES (2,'Петров')
INSERT INTO artists VALUES (3,'Сидоров')
INSERT INTO artists VALUES (4,'Федоров')
INSERT INTO artists VALUES (5,'Сергеев')
INSERT INTO artists VALUES (6,'Романов')
INSERT INTO instruments VALUES (1,'Гитара')
INSERT INTO instruments VALUES (2,'Скрипка')
INSERT INTO instruments VALUES (3,'Фортепиано')
INSERT INTO instruments VALUES (4,'Арфа')
INSERT INTO instruments VALUES (5,'Труба')
INSERT INTO links VALUES (1, 2)
INSERT INTO links VALUES (1,3)
INSERT INTO links VALUES (2,3)
INSERT INTO links VALUES (1,4)
INSERT INTO links VALUES (2,4)
INSERT INTO links VALUES (3,5)
Ну и собственно запрос:
SELECT
a.id, a.name,
i.id, i.name
FROM artists a
LEFT JOIN links l ON l.id_artist = a.id
LEFT JOIN instruments i ON l.id_instrument = i.id
WHERE i.name NOT IN ('Фортепиано', 'Арфа') or i.name IS NULL
Спасибо большое. Сейчас попробую.
120 повідомлень
#16 років тому
Можно убрать or i.name IS NULLи получить немного другой результат. Думаю, догадаетесь какой
120 повідомлень
#16 років тому
Цитата ("hobl"):То, что вы назвали джоином, то это не джоин. В оракле может быть это джоином
Я уж конечно не буду спорить насчет MySQL (т.к. не сильно знаком), но неявный джойн это не фича Оракла. Введите в поисковик implicit joins
WHERE a.field = b.field превращается в обычный INNER JOIN
посилання)
Цитата:
Example of an explicit inner join:
SELECT *
FROM employee
INNER JOIN department
ON employee.DepartmentID = department.DepartmentID
Example of an implicit inner join:
SELECT *
FROM employee, department
WHERE employee.DepartmentID = department.DepartmentID