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

Поиск:

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


Шустрый
*


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

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



Язык SQL, какой конкретно - не сказано, но личном мне ближе MySQL.

Есть 3 таблицы: KN – книги, KL – клиенты, VD – выдача книг

как-то так
Код

CREATE TABLE KN (
KKN    integer(5) NOT NULL,
N    varchar(100) NOT NULL,
A    varchar(100) NOT NULL
PRIMARY KEY(KKN))

CREATE TABLE KL (
KK    integer(5) NOT NULL,
F    varchar(100) NOT NULL
PRIMARY KEY(KK))

CREATE TABLE VD (
K    integer(5) NOT NULL,
KKN    integer(5) NOT NULL,
KK    integer(5) NOT NULL,
DT    DATETIME,
SR    integer(3) NULL
PRIMARY KEY(K))


Цитата

1. Список клиентов с полем KOL, содержащим количество выдач книг данному клиенту. Если клиенту книги не выдавались, значение этого поля должно быть не определено (использовать внешнее соединение)

я сделал так, но не уверен:
Код

SELECT *, count(vd.k) as kol FROM kl FULL OUTER JOIN vd ON kl.kk = vd.kk


Цитата

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

здесь, возможно, union надо использовать?

Цитата

3. Список клиентов, бравших одну и ту же книгу более 1 раза. В списке отобразить название книги и сколько раз она бралась.
4. Список книг, которые брались более 10 раз на срок не менее 30 дней.
5. Удалить из БД информацию о клиентах, которые ни разу не брали книги


буду благодарен за любую помощь.


Это сообщение отредактировал(а) JEEN - 10.3.2012, 19:54
PM MAIL   Вверх
JEEN
Дата 11.3.2012, 07:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



неужели никто не знает хотя бы какие функции здесь используются?
PM MAIL   Вверх
Zloxa
Дата 11.3.2012, 09:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


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

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



Цитата(JEEN @  10.3.2012,  19:51 Найти цитируемый пост)
SELECT *, count(vd.k) as kol FROM kl FULL OUTER JOIN vd ON kl.kk = vd.kk

1) Не выдержано условие
Цитата(JEEN @  10.3.2012,  19:51 Найти цитируемый пост)
Если клиенту книги не выдавались, значение этого поля должно быть не определено

Ваш запрос вернет значение 0 вместо неопределенности, если клиенту книги не выдавались
2) 
Цитата(JEEN @  10.3.2012,  19:51 Найти цитируемый пост)
FULL OUTER JOIN

2.1) Не реализован в MySQL
2.2) Не точно соответствует указанному в постановке задачи "Список клиентов"

Цитата(JEEN @  10.3.2012,  19:51 Найти цитируемый пост)
десь, возможно, union надо использовать?

Пальцем в небо?
Второе задание аналогично первому, если вы первую задачу решили самостоятельно(или хотя бы поняли принцип ее решения), совершенно не понятно ваше недоумевание над способом решения второй. smile 
Цитата(JEEN @  10.3.2012,  19:51 Найти цитируемый пост)
буду благодарен за любую помощь.

1)Не задавайте вопросы из домашних заданий
2)Для помощи лентяям существует центр помощи
3)Если вы не лентяй, попробуйте опубликовать свои версии решений. Оценим, подскажем, обсудим, но не решим за вас. smile 

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


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


Шустрый
*


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

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



Цитата

Пальцем в небо?
Второе задание аналогично первому, если вы первую задачу решили самостоятельно(или хотя бы поняли принцип ее решения), совершенно не понятно ваше недоумевание над способом решения второй.  

Я сам написал первую задачу, только нашел функцию FULL OUTER JOIN по запросу "внешнее соединение sql", почему то думал, что вернет именно null, а не ноль. А вот со второй не могу разобраться, потому что не знаю как из null сделать 0 и наоборот.

вот некоторые задачи, которые уже решил

Список книг авторов «Иванов», «Петров» и «Андреев», упорядоченный сначала по убыванию по авторам, затем по возрастанию по названиям;
Код

SELECT * FROM KN WHERE A = 'Иванов' OR A = 'Петров' OR A = 'Сидоров' ORDER BY A DESC, N ASC


Список клиентов, фамилии которых заканчиваются на «ов»;
Код
SELECT F FROM KL WHERE F like '%ов' 


Список кодов книг, которые выдавались (без повторов);
Код
SELECT DISTINCT KKN FROM VD 


Список клиентов, которым выдавались книги с указанием количества выдач;
Код
SELECT * FROM KL LEFT JOIN VD ON KL.KK = VD.KK WHERE VD.SR IS NOT NULL


последний запрос работает, только без указания количества выдач. Пытаюсь сделать так:
Код
SELECT *, count(VD.K) as count FROM KL LEFT JOIN VD ON KL.KK = VD.KK WHERE VD.SR IS NOT NULL GROUP BY VD.K

но всем книгам присваивается по одной выдаче. Почему так?

Список книг, которые не выдавались;
Код

SELECT * FROM KN LEFT JOIN VD ON KN.KKN = VD.KKN WHERE VD.KKN IS NULL


Это сообщение отредактировал(а) JEEN - 11.3.2012, 09:50
PM MAIL   Вверх
Zloxa
Дата 11.3.2012, 09:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


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

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



Цитата(JEEN @  11.3.2012,  09:43 Найти цитируемый пост)
почему то думал, что вернет именно null, а не ноль

В результате соединения, в случае отсутствия совпадения по критериям соединения, для соединяемых столбцов действительно вернется null. Но только вот количество у вас подсчитывается функцией count, которая не определенного значения не возвращает.

Цитата(JEEN @  11.3.2012,  09:43 Найти цитируемый пост)
 FULL OUTER JOIN по запросу "внешнее соединение sql"

Гуглите еще. Внешние соединения бывают трех типов. Впрочем, полное внешнее соединение в этом сулчае, при условии согласованности данных таки решает поставленную задачу. Но его применение все равно для решения задачи в этой постановке - не оправданно.

Цитата(JEEN @  11.3.2012,  09:43 Найти цитируемый пост)
WHERE VD.SR IS NOT NULL

vd.sr может принимать значение null. Фильтруясь по этому критерию вы можете упустить некоторые "выдачи"
к тому же фильтроваться вам не надо, вам все равно навдо вывести клиентов, которым ничего не выдавалось.
Цитата(JEEN @  11.3.2012,  09:43 Найти цитируемый пост)
Почему так? 

смотрите по чем группируетесь.

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


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


Шустрый
*


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

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



Цитата

смотрите по чем группируетесь.

да это уже просто так поставил, до этого группировал по VD.KK (код клиента), все равно каждому по одному ставит. Группировал по книгам, это не удовлетворяет услвию задачи, но хоть не единицы стояли.

вот кстати таблица "выдача"
user posted image

Цитата

vd.sr может принимать значение null. Фильтруясь по этому критерию вы можете упустить некоторые "выдачи"

я видимо вчера не так прочитал задачу, думал "с указанием срока выдачи". Спасибо за замечание

Это сообщение отредактировал(а) JEEN - 11.3.2012, 10:05
PM MAIL   Вверх
Zloxa
Дата 11.3.2012, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


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

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



Цитата(JEEN @  11.3.2012,  10:02 Найти цитируемый пост)
до этого группировал по VD.KK (код клиента), все равно каждому по одному ставит.

Цитата(JEEN @  11.3.2012,  10:02 Найти цитируемый пост)
вот кстати таблица "выдача"

Ну а теперь смотрите на свои данные, почему должно быть иначе.
Только клиенту 3 была выдача более одного раза, но ее вы зачем то отфильтровали по "sr is not null"
Ну и опять же, группироватсья по vd.kk - не правильно. Те клиенты, которым не было выдано ни одной книги, попадут в одну группу.



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


Шустрый
*


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

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



Цитата

Ну а теперь смотрите на свои данные, почему должно быть иначе.
Только клиенту 3 была выдача более одного раза, но ее вы зачем то отфильтровали по "sr is not null"

точно... невнимательность. Сделал так, теперь все как надо выводит
Код

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


Цитата

Ну и опять же, группироватсья по vd.kk - не правильно. Те клиенты, которым не было выдано ни одной книги, попадут в одну группу.

нам же они вообще не нужны. В условии "клиенты, которым выдавались книги". Или я не так понял опять?
PM MAIL   Вверх
Zloxa
Дата 11.3.2012, 10:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


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

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



Цитата(JEEN @  11.3.2012,  10:12 Найти цитируемый пост)
 В условии "клиенты, которым выдавались книги"

Где у нас это условие?
Я исхожу из условия в топикстарте:
Цитата(JEEN @  10.3.2012,  19:51 Найти цитируемый пост)
Если клиенту книги не выдавались, значение этого поля должно быть не определено

По этому условию нам таки нужны в результате клиенты, которым книги не выдавались.
Если же нам не нужны эти клиенты, делать внешнее соединение, а потом, с помощью условия " WHERE VD.KK IS NOT NULL" сводить результат к внутреннему - тоже нелепость.

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


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


Шустрый
*


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

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



Цитата

Список клиентов, бравших книги более 5 раз;

делаю так:
Код

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

все точно так же как и в предыдущем случае, но возникает ошибка. Разве cnt нельзя использовать в запросе?
цифру 1 я использовал вместо 5 временно, потом поправлю.

Добавлено через 1 минуту и 29 секунд
Цитата

Где у нас это условие?
Я исхожу из условия в топикстарте:

мы немного о разных задачах говорим. я вот про эту:
Цитата

Список клиентов, которым выдавались книги с указанием количества выдач;
SELECT * FROM KL LEFT JOIN VD ON KL.KK = VD.KK WHERE VD.SR IS NOT NULL

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


Чо?
****


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

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



Цитата(JEEN @  11.3.2012,  10:28 Найти цитируемый пост)
 Разве cnt нельзя использовать в запросе?

Да, нельзя.
Условия where отрабатывают до выполнения группировки, а потому не могут опираться на значения, полученные в ее результате
rtfm having

Добавлено @ 10:36
Цитата(JEEN @  11.3.2012,  10:28 Найти цитируемый пост)
мы немного о разных задачах говорим. я вот про эту:
Цитата

Список клиентов, которым выдавались книги с указанием количества выдач;
SELECT * FROM KL LEFT JOIN VD ON KL.KK = VD.KK WHERE VD.SR IS NOT NULL

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

Добавлено через 8 минут и 18 секунд
Цитата(JEEN @  11.3.2012,  10:28 Найти цитируемый пост)
мы немного о разных задачах говорим. 

Вобще, по этой самой причине, чтобы все говорили об одном и том же, обычно на один вопрос открыают один топик. 

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


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


Шустрый
*


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

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



Zloxa, огромное спасибо за помощь. Сейчас дошел до сложных задач, попытаюсь еще раз сам сделать, может выйдет что.

Список клиентов, бравших книги более 5 раз;
Код

SELECT *
FROM KL 
LEFT JOIN VD ON KL.KK = VD.KK 
WHERE VD.KK IS NOT NULL 
GROUP BY VD.KK
HAVING COUNT(VD.K) > 5

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


Чо?
****


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

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



Замечания все те же
1)
Цитата(JEEN @  11.3.2012,  10:42 Найти цитируемый пост)
LEFT JOIN VD ON KL.KK = VD.KK 
WHERE VD.KK IS NOT NULL

эквивалентно внутреннему соединению, внешнее соединение - не уместно
2) 
Цитата(JEEN @  11.3.2012,  10:42 Найти цитируемый пост)
GROUP BY VD.KK

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

Вообще запрос работать будет.
Но написан он стилистически криво.



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


Шустрый
*


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

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



сейчас напишу что узнал, потом попробую разобраться с замечаниями.

в MySQL, как я понял, нет полного внешнего объединения их заменяет левое и правое внешнее объединение (left join, right join), собственно их я и использовал, поэтому запрос для задачи:
Цитата

Список клиентов с полем KOL, содержащим количество выдач книг данному клиенту. Если клиенту книги не выдавались, значение этого поля должно быть не определено (использовать внешнее соединение)

будет выглядеть примерно так.
Код

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

если бы не "значение этого поля должно быть не определено"
выходит, что надо использовать не count, а что-то другое?
PM MAIL   Вверх
Zloxa
Дата 11.3.2012, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


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

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



Цитата(JEEN @  11.3.2012,  10:59 Найти цитируемый пост)
в MySQL, как я понял, нет полного внешнего объединения

Для решения конкретно этой задачи полного внешнего не требуется, а левое оно тоже вполне себе внешнее.  smile 

Цитата(JEEN @  11.3.2012,  10:59 Найти цитируемый пост)
если бы не "значение этого поля должно быть не определено"
выходит, что надо использовать не count, а что-то другое? 

Да, нелепое какое-то условие.
Такое ощущение, что оно добавлено преподом от какой то другой задачи.
Чтобы выполнит это условие, я бы использовал выражение case, но выглядело бы это как-то кастыльно.

Цитата(JEEN @  11.3.2012,  10:59 Найти цитируемый пост)
GROUP BY VD.KK

 smile 
Цитата(Zloxa @  11.3.2012,  10:48 Найти цитируемый пост)
 в одну группу попадут все клиенты, для которых не было выдач. 




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


 




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


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

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