Модераторы: skyboy

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> SQL. Помощь по запросам для лабораторной работы 
:(
    Опции темы
JEEN
Дата 11.3.2012, 11:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 8.3.2008

Репутация: 1
Всего: 1



Цитата

Внешнее соединение здесь не уместно.  
Благодаря условию в where оно деградирует до внутреннего(я об этом уже упоминал), фильтрация по VD.SR постановкой задачи не обусловлена.

я не понимал разницу между всеми join'ами, поэтому везде исползовал left join. Сейчас прочитал еще раз внимательно, дошло. Запрос еще проще выглядит.
фильтрация по VD.SR случайно попала, я просто скопировал со старого решения.

на счет группировки аналогично, мне казалось я все испробовал, только VD.KK работало. Сейчас сгруппировал по KL.KK, получилось. В общем, задача:
Цитата

Список клиентов, которым выдавались книги с указанием количества выдач

старое решение
Код

SELECT *, count(VD.K) as cnt 
FROM KL 
LEFT JOIN VD ON KL.KK = VD.KK 
WHERE VD.KK IS NOT NULL 
GROUP BY VD.KK 

новое решение
Код

SELECT *, count(VD.K) as cnt 
FROM KL 
INNER JOIN VD ON KL.KK = VD.KK 
GROUP BY KL.KK

PM MAIL   Вверх
JEEN
Дата 11.3.2012, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 8.3.2008

Репутация: 1
Всего: 1



Цитата

Список книг с указанием, сколько раз она выдавалась (поле KOL) и среднего срока выдачи (поле SR). Если книга не выдавалась, она должна присутствовать в списке, KOL=0, SR=0;

Код

SELECT *, count(VD.K) as KOL, avg(VD.SR) as SR
FROM KN
LEFT JOIN VD ON KN.KKN = VD.KKN
GROUP BY KN.KKN

только функция avg не выдает 0, если книгу не брали..
PM MAIL   Вверх
Zloxa
Дата 11.3.2012, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(JEEN @  11.3.2012,  11:21 Найти цитируемый пост)
я не понимал разницу между всеми join'ами, поэтому везде исползовал left join.

Я именно так и понял, потому и был так настойчив smile

Цитата(JEEN @  11.3.2012,  11:21 Найти цитируемый пост)
дошло

Чисто чтоб закрепить - я как-то рисовал картинку. Мне кажется достаточно доходчиво должно бы быть. 

Цитата(JEEN @  11.3.2012,  11:21 Найти цитируемый пост)
новое решение

 smile 
Осталось одно только замечание. Это будет работать только на MySQL.

Стандарт SQL запрещает в списке полей select использовать поля, не перечисленные в group by без применения к ним аггрегатных функций. MySQL единственный из известных мне движков не реализует этого запрета. Разработчики отписываются, мол это для оптимизации, и ограничивают область использования этой фичи в документации. 

Соответственно, чтобы оторваться от диалекта MySQL вам осталось лишь выдержать это ограничение заменив 
Код

SELECT *, count(VD.K) as cnt 

на
Код

select KL.KK,max(kl.F) as F,  count(VD.K) as cnt 


Добавлено через 4 минуты и 39 секунд
Цитата(JEEN @  11.3.2012,  11:43 Найти цитируемый пост)
только функция avg не выдает 0, если книгу не брали.. 

Код

coalesce(avg(VD.SR),0)  as avg_SR


Тут, кстати, тонкий момент. VD.SR может принимать неопределенное значение, и если оно используется, функция avg его не будет использовать при расчете. avg([1,null]) = 1, в то время, как avg([1,0]) = 0.5. Но в постановке задачи этот ньюанс не огооврен, думаю, можно забить(но держать в уме, я бы такой вопрос поднял бы на защите)


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
JEEN
Дата 11.3.2012, 12:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 8.3.2008

Репутация: 1
Всего: 1



Цитата

Чисто чтоб закрепить - я как-то рисовал картинку. Мне кажется достаточно доходчиво должно бы быть. 

хорошие картинки, как-то давно натыкался на подобное, только там круги были. Тогда не сохранил и забыл где видел, а вашу картинку сохранил на комп)

Цитата

max(kl.F) as F

я так понял здесь без разницы что max, что min использовать? лишь бы была какая-то функция?

Цитата

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

получилось) только у преподавателя даже нет возможности спросить/проконсультироваться. На дистанционке учусь.

вот еще пару запросов сделал, может есть какие-то замечания..
Цитата

Добавить в БД: книга «Колобок», с кодом 234, автор не задан

Код

INSERT INTO KN 
SET KKN = ‘234’, N = ‘Колобок’


Цитата

Удалить из БД информацию о клиентах, которые ни разу не брали книги

Код

DELETE KL FROM KL 
LEFT JOIN VD ON KL.KK=VD.KK 
WHERE VD.KK IS NULL


остались 2 задачи, которые никак не получаются.
Цитата

1 задача: Список книг, которые брались более 10 раз на срок не менее 30 дней.

сделал вот так:
Код

SELECT *
FROM KN
INNER JOIN VD ON KN.KKN = VD.KKN
WHERE VD.SR > 30
GROUP BY KN.KKN
HAVING COUNT(VD.K) > 10

но здесь мешает HAVING COUNT, потому что он считает, что должно быть больше 10 записей, которые брались больше чем на 30 дней. Т.е. сначала выполняется WHERE, отсеивает часть, потом по оставшимся уже проходится HAVING COUNT. А надо как-то, чтобы они вместе работали, например WHERE VD.SR > 30 and count(VD.K) > 10, но тогда GROUP BY мешает.

Цитата

Задача 2. Список клиентов, бравших одну и ту же книгу более 1 раза. В списке отобразить название книги и сколько раз она бралась

эм.. тут я даже не представляю как должен вывод выглядеть, речь о 2х разных списках идет. Что-то такого что ли:
- Иванов, Петров, Сидоров - Горе от ума (3)
- Иванов, Козлов - Евгений Онегин (2)
и т.д.
разве такой список можно сделать только одним запросом?

в общем, я бы, наверное, прошелся по списку книг, у каждой проверял кто ее брал, если ее брали > 1 человека, то выводить ее..
PM MAIL   Вверх
Zloxa
Дата 11.3.2012, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(JEEN @  11.3.2012,  12:48 Найти цитируемый пост)
я так понял здесь без разницы что max, что min использовать? лишь бы была какая-то функция?

 smile т.к. у нас группировка по первичному ключу.

Цитата(JEEN @  11.3.2012,  12:48 Найти цитируемый пост)
DELETE KL FROM KL 
LEFT JOIN VD ON KL.KK=VD.KK 
WHERE VD.KK IS NULL

тут не знаю. Я пишу на оракле. Оракл не умеет делать жойн для делита. not in или not exists с моей точки зрения выглядило бы как более универсальное решение. C not in - ньюанс: применимо только к not nullable набору данных.
Цитата(JEEN @  11.3.2012,  12:48 Найти цитируемый пост)
 более 10 раз на срок не менее 30 дней.

Здесь возможна неоднозначность трактовки задачи
1) Книга бралась более 10 раз и всякий раз на срок не менее 30 дней, тогда ваш подход - правильный
2) Книга бралась более 10 раз на общий срок не менее 30 дней, тогда суммируем сроки и отсекаем в havind

Мне кажется первый вариант самый близкий к исходной задаче, и вы соврешенно правильно его реализовали.
Хотя второй вариант тоже похож на правду.
Цитата(JEEN @  11.3.2012,  12:48 Найти цитируемый пост)
эм.. тут я даже не представляю как должен вывод выглядеть

В принципе - то же самое. Группироваться по паре (id_клиент,id_книга)


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
JEEN
Дата 11.3.2012, 14:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 88
Регистрация: 8.3.2008

Репутация: 1
Всего: 1



Цитата

В принципе - то же самое. Группироваться по паре (id_клиент,id_книга)

у меня серьезные проблемы с пониманием условий %) перечитал 200 раз и до меня дошло, что "Список клиентов, бравших одну и ту же книгу" эту фразу я не так понимаю, думал что нужно найти общие интересы клиентов)) в общем сделал вот так
Код

SELECT *, count(VD.K) as KOL, max(KL.F) as F, max(KN.N) as N
FROM KL
INNER JOIN VD ON KL.KK = VD.KK 
INNER JOIN KN ON VD.KKN = KN.KKN 
GROUP BY KL.KK, VD.KKN
HAVING COUNT(VD.K) > 1

все работает как надо.

Zloxa, спасибо вам огромное. Без вас бы не разобрался. Поставил бы плюсик к каждому посту, но пока 100 сообщений не набрал, нельзя плюсики ставить.
PM MAIL   Вверх
Zloxa
Дата 11.3.2012, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(JEEN @  11.3.2012,  14:07 Найти цитируемый пост)
спасибо вам огромное

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

Это сообщение отредактировал(а) Zloxa - 11.3.2012, 14:20


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Zloxa
Дата 11.3.2012, 14:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(JEEN @  11.3.2012,  14:07 Найти цитируемый пост)
найти общие интересы клиентов

Так то это тоже просто. 

Селфджойн:
Код

select * from vd vd1 inner join vd vd2 on vd1.KKN= vd2.KKN and vd1.kk != vd1.kk

получаем список общих интересов  smile 


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.1081 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.