SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 23.04.2011 13:36:19

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

3 непонятных запроса

1. Найдите пары классов, имеющих одинаковые калибр орудий и страну. В результате каждая пара указывается только один раз, т.е. (i,j), но не (j,i), Порядок вывода: класс 1, класс 2, калибр орудия и страна. (SELECT)
2. Добавить отсутствующие в таблице Ships головные корабли из Outcomes. Годом спуска на воду считать средний округленный до целого числа год по кораблям страны добавляемого корабля. Если средний год неизвестен, запись не вносить. (DML)
3. Потопить в следующем сражении суда, которые в первой своей битве были повреждены и больше не участвовали ни в каких сражениях. Если следующего сражения для такого судна не существует в базе данных, не вносить его в таблицу Outcomes. Замечание: в базе данных нет двух сражений, которые состоялись бы в один день.(DML)

Рассматривается БД кораблей, участвовавших во второй мировой войне. Имеются следующие отношения:

Battles (name, date)
Classes (class, type, country, numGuns, bore, displacement)
Outcomes (ship, battle, result)
Ships (name, class, launched)

Корабли в «классах» построены по одному и тому же проекту, и классу присваивается либо имя первого корабля, построенного по данному проекту, либо названию класса дается имя проекта, которое не совпадает ни с одним из кораблей. Корабль, давший название классу, называется головным.

Отношение Classes содержит имя класса, тип (bb для боевого (линейного) корабля или bc для боевого крейсера), страну, в которой построен корабль, число главных орудий, калибр орудий (диаметр ствола орудия в дюймах) и водоизмещение ( вес в тоннах). В отношении Ships записаны название корабля, имя его класса и год спуска на воду. В отношение Battles включены название и дата битвы, в которой участвовали корабли, а в отношении Outcomes – результат участия данного корабля в битве (потоплен-sunk, поврежден - damaged или невредим - OK). Замечание. В отношение Outcomes могут входить корабли, отсутствующие в отношении Ships.


Прикрепленные файлы:
Attachment Icon ships.txt, Размер: 5,187 байт, Скачано: 953

Неактивен

 

#2 23.04.2011 13:38:40

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

У меня просто мозг клинит, когда я пытаюсь понять условия запросов. Не могли бы Вы, если не сложно, все по шагам хотя бы описать, но, если не затруднит, то и написать. Спасибо.

Неактивен

 

#3 24.04.2011 15:51:25

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

Прошу обратить внимание. Мне очень интересно понять структуру данных запросов.

Неактивен

 

#4 25.04.2011 11:23:51

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

Люди, Вы где? Сильно помощь Ваша нужна...

Неактивен

 

#5 25.04.2011 20:06:29

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: 3 непонятных запроса

Люди отдыхают по выходным wink

1. Первая задача простая, кроме условия, что нужно указывать пару только один раз. Нужно просто придумать какое-то хитрое условие выбора пары. Например, i < j:

select c1.class, c2.class, c1.bore, c1.country from Classes c1, Classes c2 WHERE c1.country = c2.country AND c1.bore = c2.bore AND c1.class < c2.class;

2. Тут неплохо разбить задачку на два этапа: а) найти корабли, которые есть в исходах, но которых нет в таблице классов (LEFT JOIN) б) добавить эти корабли (подзапрос + INSERT). Думаю, справитесь.

3. Это единственное плохо понимаемое условие. Но такие случаи действительно бывают. То есть в первой схватке корабль зацепили, и во второй — тоже зацепили. Тогда он побывал в двух схватках и при этом еще не потонул smile

Хорошего простого решения тут сходу не вижу. Но можно сделать рекогносцировку и выяснить, что дважды в бою побывал только один корабль wink

Неактивен

 

#6 25.04.2011 20:19:07

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

Спасибо. Хорошо, я подумаю. Если не получится, спрошу. Извиняюсь, если потревожил.

Неактивен

 

#7 25.04.2011 21:49:17

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

1. С этой задачей разобрался. Вы правы, она не сложная.
2. Не понимаю, зачем связывать с таблицей классов на данном этапе? Тут бы просто выборку получить. Сколько не пробую использоваться LEFT JOIN всегда получаю только значения из левой таблицы, соотношения со связанной нет.
3. Тут я вообще молчу. Я в этой задаче только слова понимаю.

Отредактированно pkhell (25.04.2011 21:51:29)

Неактивен

 

#8 25.04.2011 21:53:39

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

Вы уж не ругайтесь. Я действительно не могу сообразить.

Неактивен

 

#9 26.04.2011 19:58:07

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: 3 непонятных запроса

Ну, Вы попробуйте для начала получить список тех кораблей, которые есть
в исходах, но которых нет в таблице классов. Любым способом.

Неактивен

 

#10 27.04.2011 15:45:53

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

Нашел общие корабли среди Outcomes и Classes. Их оказалось 2. Но вот заставить исключить их из выборки не получается. Пробовал и NOT, и даже (NOT) EXISTS. Как можно создать исключающий запрос?

Неактивен

 

#11 28.04.2011 20:52:18

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: 3 непонятных запроса

SELECT ... FROM a LEFT JOIN b ON a.field_a = b.field_b WHERE b.field_b IS NULL.

Левое объединение подставляет NULL в случае, когда в правой таблице нет
данных. Соответственно, можно использовать это в WHERE.

Неактивен

 

#12 28.04.2011 21:17:29

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

Вы сказали, что нужно вывести корабли из исходников (Outcomes и Ships), которых нет в таблице Classes. Получилось следующее:

SELECT ship
FROM Outcomes
LEFT JOIN Classes ON Outcomes.ship = Classes.class
WHERE Classes.class IS NULL
UNION ALL
SELECT Name
FROM Ships
LEFT JOIN Classes ON Ships.Name = Classes.class
WHERE Classes.class IS NULL

Верно ли это? Если да, то то делать дальше. Если нет, пожалуйста, напишите так, как должно быть.

Отредактированно pkhell (28.04.2011 21:19:07)

Неактивен

 

#13 28.04.2011 23:55:16

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: 3 непонятных запроса

Первая часть — да. А зачем нужна вторая? Вам же надо добавить те корабли,
которые есть в исходах, но нет в списке кораблей? Т.е. только первую часть?

Неактивен

 

#14 29.04.2011 00:12:24

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

По сути, исходя из задания, нужно из таблицы Outcomes добавить головные корабли в таблицу Ships, то есть те, которые есть в outcomes и нет в Ships. Я так понимаю задание. Таблица Classes нужна только для выборки. Или все не так? Это все по поводу задачи №2.

Неактивен

 

#15 29.04.2011 00:16:43

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

Получается, что запрос на отсутствующие корабли в таблице ships должен выглядеть следующим образом:

SELECT Ship
FROM Outcomes
LEFT JOIN Ships ON Ships.Name = Outcomes.ship
WHERE Ships.name IS NULL

Неактивен

 

#16 29.04.2011 11:17:32

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: 3 непонятных запроса

Воо, замечательно. Проблема в том, что мы не можем далее никаким образом
угадать, какой стране принадлежит тот или иной корабль. Кроме некоторых
(которые есть в Classes). Посему предлагаю присоединить еще таблицу Classes
внутренним объединением, таким образом отсеяв корабли, для которых мы мо-
жем сделать хоть что-то:

Код:

[silentia] root test > SELECT o.ship, c.country FROM Outcomes o LEFT JOIN Ships s ON o.ship = s.name JOIN Classes c ON c.class = o.ship WHERE s.name IS NULL;
+----------+---------+
| ship     | country |
+----------+---------+
| Bismarck | Germany |
+----------+---------+
1 row in set (0.00 sec)

Ну и задача, как я понимаю, состоит в том, чтобы добавить этот корабль в Ships.

Неактивен

 

#17 29.04.2011 18:30:18

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

Я все меньше начинаю понимать запрос, с которым мы с Вами работаем. Получается, что из всех кораблей, которые были в выходной запросе, только один имеет страну. Это хорошо. Теперь смотрим в таблицу ships и видим, что с у данной страны нет года спуска на воду. Получается, что, согласно условию, такой корабль добавлять не стоит. Я так понимаю? Мне вот теперь только интересно, зачем в условии написано "корабли", когда запросом INSERT можно за раз добавить только одну строчку? В общем, я пока сделал так:

INSERT INTO Ships (name)
SELECT r.ship
FROM (
SELECT o.ship, c.country
FROM Outcomes o
LEFT JOIN Ships s ON o.ship = s.name
JOIN Classes c ON c.class = o.ship
WHERE s.name IS NULL
) AS R
.
Данный запрос вносит имя корабля, но как добавить его класс и сделать фильтр по добавлению по году спуска - этого я не знаю. Жду Вашего мнения. ))

Отредактированно pkhell (29.04.2011 18:32:17)

Неактивен

 

#18 30.04.2011 15:30:00

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: 3 непонятных запроса

Нет, страна есть у каждого корабля, просто у некоторых кораблей мы страну
не знаем (хотя, можем догадываться по названию, например).

Сделать точно так же — подзапросами. Нужно выбрать средний год спуска в
этой стране, а класс Вы знаете, т.к. с табличкой классов объединение уже
было (и, учитывая условие, он совпадает с названием корабля wink).

Неактивен

 

#19 30.04.2011 18:01:08

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

Я правильно понимаю, что добавлять мы имеем право только корабль Bismark? Но почему? Класс знаю я, но надо же сделать так, чтобы автоматически SQL по-классу определял страну и год спуска на воду, ведь иначе не правильно будет. Или я совсем туплю?)))

Неактивен

 

#20 30.04.2011 18:09:18

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: 3 непонятных запроса

Представьте, что Вы пришли в зоопарк. Ваша задача — записать на листочке
всех животных, которые живут на полюсах. В качестве помощи в этой нелегкой
задаче, Вам дают справочник птиц. Вы можете, в соответствии со справочником,
найти пингвина, а вот белого медведя Вы найти не можете, потому что он не
птица smile

Точно так же и у Вас — у Вас есть куча кораблей, которые подходят под условие
«участвовали, но нет в списке», но только один из них есть в справочнике.

Напишите отдельный подзапрос для года спуска — и задача решена.

Неактивен

 

#21 30.04.2011 18:32:37

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

Подробно объяснили. Попробую реализовать. )

Неактивен

 

#22 02.05.2011 18:47:50

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

Итак, я поэкспериментировал и пришел к выводу, что получить год спуска у данного корабля нельзя, так как в базе подобное информации нет, либо я не могу ее найти. На данный момент я сделал INSERT на добавление еще и класса, но он, почему-то, не работает, выдает ошибку синтаксиса в Pma:

INSERT INTO Ships (name, class)
SELECT r.ship
FROM (
SELECT o.ship, c.country
FROM Outcomes o
LEFT JOIN Ships s ON o.ship = s.name
JOIN Classes c ON c.class = o.ship
WHERE s.name IS NULL
) AS R,
SELECT Classes.class
FROM Classes
JOIN (
SELECT o.ship, c.country
FROM Outcomes AS o
LEFT JOIN Ships AS s ON o.ship = s.name
JOIN Classes AS c ON c.class = o.ship
WHERE s.name IS NULL
) AS N ON Classes.country = N.country
 

Жду Ваших советов и наставлений. smile

Неактивен

 

#23 03.05.2011 16:04:48

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

Итак, запрос на добавление корабля и класса:

INSERT INTO Ships (name, class) VALUES (
(SELECT r.ship
FROM (
SELECT o.ship, c.country
FROM Outcomes o
LEFT JOIN Ships s ON o.ship = s.name
JOIN Classes c ON c.class = o.ship
WHERE s.name IS NULL
) AS R),
(SELECT Classes.class
FROM Classes
JOIN (
SELECT o.ship, c.country
FROM Outcomes AS o
LEFT JOIN Ships AS s ON o.ship = s.name
JOIN Classes AS c ON c.class = o.ship
WHERE s.name IS NULL
) AS N ON Classes.country = N.country))

Как добавить дату... не знаю...

Неактивен

 

#24 04.05.2011 01:13:15

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: 3 непонятных запроса

Точно так же — SELECT AVG(launched) FROM Ships JOIN Classes USING(class) JOIN ( подзапрос, определяющий страну )

Неактивен

 

#25 04.05.2011 16:48:25

pkhell
Активист
Зарегистрирован: 23.03.2011
Сообщений: 127

Re: 3 непонятных запроса

Суть не в том, как написать запрос. Суть в том, что у германских кораблей нет года спуска. )) Мне преподаватель сказал, что надо свой корабль добавить. ))

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson