| Автор |
Сообщение |
Сообщения: 8
Страна: Россия |
 03.09.2008 в 12:42
Есть таблица актеров пусть наз-ся akter со столбцами (id,fio,adres), и у каждого актера есть характеристики
например : владение музыкальными иструментами.
Таблица для подобных характеристик иммет поля (id, name), пусть для "владения муз. инструментами" таблица будет наз-ся tb1.
Для хранения таких характеристик для каждого актера есть еще таблицы с полями (id,harID - id записи из таблицы характеристик, akterID - id актера).
Пусть для "владения муз. инструментами" такая таблица имеет имя tb1_svaz.
Вопрос такой: как сделать выборку чтобы показались все актеры не владеющии 2 определенными характеристиками. Например актеры не играющие на гитаре и скрипке ?
заранее спасибо. надеюсь ясно объяснил
|
Сообщения: 8
Страна: Россия |
 03.09.2008 в 12:58
Цитата (hobl): Т.е. tb1 содержит названия инструментов? а tb1_svaz соотвествие между музыкантом и инструментом?
В итоге имеем: таблица Музыкант(Идентификатор музыканта, Имя), Инструмент(Идентификатор инструмента, Название), Соответствие(Идентификатор, Идентификатор музыканта, Идентификатор инструмента). Поставить запрос: найти музыкантов, которые не владеют двумя заданными инструментами?
Так это дет. сад
Напиши пожалуйста SQL запрос
|
Сообщения: 957
Страна: Украина |
 03.09.2008 в 13:05 [Отредактировано: 03.09.2008 в 13:05]
Код: select актери.*
from актери, интсрументы
where (актеры.id = инуструменты.id_актера) and (инстурменты.id not in (id_перового_иснтурумента, id_второго_иснтурумента))
это же элементарно)
П.С. Также можно на джойнах это реализовать, только я их не люблю особенно)
|
Сообщения: 8
Страна: Россия |
 03.09.2008 в 13:07
Цитата (MMM_Corp): Код: select актери.*
from актери, интсрументы
where (актеры.id = инуструменты.id_актера) and (инстурменты.id not in (id_перового_иснтурумента, id_второго_иснтурумента))
это же элементарно)
П.С. Также можно на джойнах это реализовать, только я их не люблю особенно)
спасибо.
|
Сообщения: 1024
Страна: Россия |
 03.09.2008 в 13:27
Цитата (MMM_Corp): Код: select актери.*
from актери, интсрументы
where (актеры.id = инуструменты.id_актера) and (инстурменты.id not in (id_перового_иснтурумента, id_второго_иснтурумента))
Мда... Давно такого не видел.
Автор, не делай так, используй джойны.
Только уточни СУБД.
|
Сообщения: 1724
Страна: Украина |
 03.09.2008 в 13:43 [Отредактировано: 03.09.2008 в 13:58]
Вариант 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, и т.д.
|
Сообщения: 1024
Страна: Россия |
 03.09.2008 в 13:58
tvv, можно куда проще, через left join.
|
Сообщения: 8
Страна: Россия |
 03.09.2008 в 13:59
Цитата (alibek): Цитата (MMM_Corp): Код: select актери.*
from актери, интсрументы
where (актеры.id = инуструменты.id_актера) and (инстурменты.id not in (id_перового_иснтурумента, id_второго_иснтурумента))
Мда... Давно такого не видел.
Автор, не делай так, используй джойны.
Только уточни СУБД.
субд MYSQL
|
Сообщения: 8
Страна: Россия |
 03.09.2008 в 14:01
Select актери.*
from актери, интсрументы
where (актеры.id = инуструменты.id_актера) and (инстурменты.id not in (id_перового_иснтурумента, id_второго_иснтурумента))
так попробовал, не совсем верно получилось. так как если актер играет например на гитаре, скрипке, барабанах по его все равно показывает. так как барабаны не входят в условие
|
Сообщения: 957
Страна: Украина |
 03.09.2008 в 14:02
Цитата (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_актера) , что указивает на явную связь актер-инстуремнт на котором он играет, что исключает попадание сюда актеров которые ни на чем не играют!
|
Сообщения: 8
Страна: Россия |
 03.09.2008 в 14:03 [Отредактировано: 03.09.2008 в 14:07]
Цитата (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, и т.д.
Спасибо. Сейчас попробую. Названия таблиц не такие. Они слишком длинные поэтому я их тут сократил
|
Сообщения: 957
Страна: Украина |
 03.09.2008 в 14:04 [Отредактировано: 03.09.2008 в 14:06]
Укажите СУБД, сделайте SQL-дамп, потом обсудим.
П.С. Больше на меня не ссылайтесь, работы полно, да и все равно на моем примере идея разворачивается 
|
Сообщения: 1724
Страна: Украина |
 03.09.2008 в 14:18 [Отредактировано: 03.09.2008 в 14:25]
Цитата (MMM_Corp): Это еще почему? Я видь указал : Код: where (актеры.id = инуструменты.id_актера) , что указивает на явную связь актер-инстуремнт на котором он играет, что исключает попадание сюда актеров которые ни на чем не играют!
Вот именно, исключает.
А условие было такое, что нужно вывести всех актеров, которые не играют на гитаре и скрипке.
Если актер не играет ни на каком инструменте, то это значит, что он в том числе не играет на гитаре и скрипке, и по условию его тоже нужно выводить, не так ли?
Вы же вывели актеров, которые обязательно играют на чем-то, что не гитара и не скрипта, причем если актер играет еще и на контрабасе и пианино, он выведется дважды (в Вашем случае DISTINCT нужно еще указать, или GROUP BY).
Цитата (alibek): tvv, можно куда проще, через left join.
Я не думаю что через LEFT JOIN проще (учитывая, что нужно помнить о группировке по актеру).
Да и по производительности спорно какой вариант лучше, нужно делать замеры на реальных наборах данных.
Вот напишите Ваш вариант запроса, подумаем, обсудим.
|
Сообщения: 98
Страна: Россия |
 03.09.2008 в 14:35
Цитата (MMM_Corp): П.С. Также можно на джойнах это реализовать, только я их не люблю особенно)
Код: from a, b where a.field = b.field
Это тоже джойн, только неявный
|
Сообщения: 98
Страна: Россия |
 03.09.2008 в 14:52 [Отредактировано: 03.09.2008 в 14:56]
Таблицы
Код:
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
|
Сообщения: 268
Страна: Украина |
 03.09.2008 в 14:54
То, что вы назвали джоином, то это не джоин. В оракле может быть это джоином
|
Сообщения: 98
Страна: Россия |
 03.09.2008 в 14:55
Если убрать секцию WHERE, то получим полный список:
Цитата: 1 Иванов 2 Скрипка
2 Петров 3 Фортепиано
1 Иванов 3 Фортепиано
2 Петров 4 Арфа
1 Иванов 4 Арфа
3 Сидоров 5 Труба
4 Федоров
5 Сергеев
6 Романов
А если с WHERE, то получим искомый результат:
Цитата: 1 Иванов 2 Скрипка
3 Сидоров 5 Труба
4 Федоров
5 Сергеев
6 Романов
|
Сообщения: 8
Страна: Россия |
 03.09.2008 в 14:57
Цитата (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
Спасибо большое. Сейчас попробую.
|
Сообщения: 98
Страна: Россия |
 03.09.2008 в 14:57
Можно убрать и получить немного другой результат. Думаю, догадаетесь какой
|
Сообщения: 98
Страна: Россия |
 03.09.2008 в 15:02
Цитата (hobl): То, что вы назвали джоином, то это не джоин. В оракле может быть это джоином
Я уж конечно не буду спорить насчет MySQL (т.к. не сильно знаком), но неявный джойн это не фича Оракла. Введите в поисковик implicit joins
WHERE a.field = b.field превращается в обычный INNER JOIN
http://en.wikipedia.org/wiki/join_(SQL)
Цитата: 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
|