Роман И.
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, и т.д.
Болатов А.
1090 повідомлень
#16 років тому
tvv, можно куда проще, через left join.
Роман И.
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