Ефективно из трех таблиц

Yurik

/dev/null
Ефективно из трех таблиц

Есть три таблицы: книги, инвентарные номера и приём-выдача

PHP:
+--------+    +--------+    +--------+
| books  |    |  invno |    |  rent  |
+--------+    +--------+    +--------+
|  id    |----| idbook | +- | idinvno|
| descr  |    | invno  | |  | id_who |
+--------+    | idinvno|-+  | dateout|
              +--------+    | datein |
                            +--------+
Хотелось бы сделать запрос, который бы выводил только те книги которые имеют хоть один имеющийся в наличии инвентарный номер, т.е. не выводить те книги у которых для всех idinvno в таблице rent datein='0000-00-00', т.е. приёма ещё не было.
Таблицы сравнительно большие и обыкновенные запросы на выборку книг выполняются не очень быстро (сравнительно). Если ко всему этому ещё прицепить две таблицы, которые больше первой, то время выполнения запроса будет очень существенным.
Как это можно сделать поефективней.
P.S. ИМХО нужно добавить boolean поле в таблицу книг и при выдаче книги проверять остался ещё хоть один экземпляр или нет, и если нет, то поставить в поле 'N', а при приёме - 'Y'. Но это уже как бы дублирование информации и привязка к скрипту приёма-выдачи. Хотелось бы более независимое решение.
 

tony2001

TeaM PHPClub
Юрик, ты отформатируй "эскиз" таблиц - из текста оч. мало понятно.
 

tony2001

TeaM PHPClub
Код:
mysql> desc db;
+-----------------+-----------------+------+-----+---------+-------+
| Field           | Type            | Null | Key | Default | Extra |
+-----------------+-----------------+------+-----+---------+-------+
| Host            | char(60) binary |      | PRI |         |       |
| Db              | char(64) binary |      | PRI |         |       |
| User            | char(16) binary |      | PRI |         |       |
| Select_priv     | enum('N','Y')   |      |     | N       |       |
| Insert_priv     | enum('N','Y')   |      |     | N       |       |
| Update_priv     | enum('N','Y')   |      |     | N       |       |
| Delete_priv     | enum('N','Y')   |      |     | N       |       |
| Create_priv     | enum('N','Y')   |      |     | N       |       |
| Drop_priv       | enum('N','Y')   |      |     | N       |       |
| Grant_priv      | enum('N','Y')   |      |     | N       |       |
| References_priv | enum('N','Y')   |      |     | N       |       |
| Index_priv      | enum('N','Y')   |      |     | N       |       |
| Alter_priv      | enum('N','Y')   |      |     | N       |       |
+-----------------+-----------------+------+-----+---------+-------+
13 rows in set (0.00 sec)
[ code ] [ /code ]
используй (без пробелов, конечно.)
 

Yurik

/dev/null
Нпихали там всяхих РАЗМЕРОМ, ШРИФТОМ чтобы народ пугать.....
 

tony2001

TeaM PHPClub
Юрик, ты о чем?
нет таких тэгов в этом форуме, это ты их придумал.
 

mahoune

Guest
IMHO Я думаю что всю твою проблему с учетом скорости можно решить стандартными JOIN'ами и индексами.
 

chira

Новичок
select distinct b.id, b.descr
from books b LEFT JOIN invno i ON b.id = i.idbook
LEFT JOIN rent r i.idinvno=r.idinvno
WHERE r.datein='0000-00-00' OR r.idinvno IS NULL
 

Yurik

/dev/null
1. !!!
Если rent пуста, т.е. книга (любой из её инв. номеров) никогда не выдавались, то JOIN не подойдет ибо нечего джойнить
2. !!!
Если книга выдается не в первой, то в rent будет несколько записей:
1 187912 2002-09-09 2002-10-10
2 187912 2002-11-11 0000-00-00
 

mahoune

Guest
1.
Ну так это нормально! Там будет в поле NULL на него и проверяют :)
 

Yurik

/dev/null
Тоесть если мы опустошим rent:
DELETE FROM rent; (никто ничего не брал)
то приведенный JOIN выведет все книги?

Это также невероятно как СТО Ейнштейна, но я попробую.
 

Yurik

/dev/null
Уважаемые господа, я уже попробовал и признаюсь вам это туфта. Если хоть одна из таблиц пуста, нифига запрос с JOIN не выведет и никакие условия типа IS NULL этого не меняют
 

chira

Новичок
Уважаемые господа, я уже попробовал и признаюсь вам это туфта. Если хоть одна из таблиц пуста, нифига запрос с JOIN не выведет и никакие условия типа IS NULL этого не меняют
Ты вообще думаешь о чем говоришь "Если хоть одна из таблиц пуста" туфтолог ты наш. Пустой может быть таблица rent. Про JOINы хоть читал или способен только на определение туфты.

Давай примеры данных для таблиц и свой SQL.
 

Crazy

Developer
Автор оригинала: Yurik
Если хоть одна из таблиц пуста, нифига запрос с JOIN не выведет
Друг мой, а почему бы Вам не обратиться к документации как к хорошему способу избежать позора? :)
 

Yurik

/dev/null
Я занимаюсь не туфтой а тестированием опытным путём того что вы мне сказали и не надо здесь RTFM'эмиться.
Запрос
Код:
SELECT * FROM
(books INNER JOIN invno ON books.id=invno.idbook)
INNER JOIN rent ON invno.idinvno=rent.idinvno
WHERE rent.idinvno Is Null;
Структура та же что в начале топика.
Данные:
------------
books- id от 1 до 8 (descr-любые)
invno- для каждого из восьми idbook (1..8) по 3 номера (любых)
Получается idinvno от 1..24
rent-пустая
------------
Запрос возвращает 0 записей
Если добавить что-нибудь в "rent", то запрос выводит эту книгу.
 

mahoune

Guest
И при чем тут INNER JOIN когда тебе аглицким языком писали LEFT JOIN или для тебя это одно и тоже?! :)

Посмотри этот скрипт! Тут все подписано! И все ссылочки куда надо!
SELECT DISTINCT b.id, b.descr
FROM books b LEFT JOIN invno i ON b.id = i.idbook
LEFT JOIN rent r i.idinvno=r.idinvno
WHERE
r.datein='0000-00-00'
OR
r.idinvno IS NULL
 

Yurik

/dev/null
If you use LEFT JOIN to find rows that don't exist in some table and you have the following test: column_name IS NULL in the WHERE part, where column_name is a column that is declared as NOT NULL, then MySQL will stop searching after more rows (for a particular key combination) after it has found one row that matches the LEFT JOIN condition.
С этим я до конца не разобрался. Когда он stop search??
 
Сверху