Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Web программирование > SQL, базы данных
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.07.2011, 22:05   #1
Macklay
Пользователь
 
Аватар для Macklay
 
Регистрация: 27.06.2009
Сообщений: 30
Печаль Поиск совпадений в нескольких таблицах

Здравствуйте, уважаемые! Есть такая задача. Необходимо средствами SQL получить из нескольких таблиц записи, которые есть в двух, в трех либо во всех.
Структура такая: ID, Tovar, Sklad.
Например, есть таблички:
Table1:
| 1 | Ручка | Склад1 |;
| 2 | Карандаш | Склад1 |;
| 1 | Ластик | Склад1 |
Table2:
| 1 | Ручка | Склад2 |;
| 1 | Карандаш | Склад2 |;
| 1 | Линейка | Склад2 |;
Table3:
| 1 | Транспортир | Склад3 |;
| 1 | Пенал | Склад3 |;
| 1 | Ручка | Склад3 |.

Фактически каждая таблица это один отдельный склад.
Поэтому у таблиц одинаковая структура:
На выходе нужно получить что-то вроде этого:
Склад1 Склад2 Склад3 РУЧКА.
Склад1 Склад2 КАРАНДАШ.

Помогите реализовать.. Буду рад любым вариантам.. Спасибо!
Macklay вне форума Ответить с цитированием
Старый 26.07.2011, 23:19   #2
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

что является уникальным идентификатором, однозначно определяющим товар?! (должен быть Артикул или ШифрТовара)..

Или Вы считаете, что наименование товара Tovar - это однозначно определяет уникальность товара?!!

Тогда Вы неправы!

а по сути вопроса.
чтобы найти товар, который есть на всех трёх складах достаточно написать:
Код:
select * from Table1, Table2, table3
  where Table1.Tovar = Table2.Tovar
     and Table2.Tovar = Table3.Tovar

p.s. запрос 100% рабочий. Но я при этом весьма сомневаюсь, что это запрос применим на практике... но! Какой вопрос - такой и ответ...
Serge_Bliznykov вне форума Ответить с цитированием
Старый 27.07.2011, 00:23   #3
pproger
C++ hater
Старожил
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

2Serge_Bliznykov
cross join... жесть))
Код:
select *
from table1
where exists (select * from table2 where table2.tovar = table1.tovar)
and exists (select * from table3 where table3.tovar = table1.tovar)
если tovar индексируемое поле - будет быстро

автору:
корявая у тебя структура таблиц.
как надо:
1-ая таблица: товары. описание каждого товара (наименование, вес, какие нить свойства товара)
2-ая таблица: список складов. (название, адрес и тд)
3-ая таблица: связь склада с товарами (id товара, id склада, кол-во товара)

тогда показать товары, которые есть на Складе1, Складе2 и Складе3 можно так:
Код:
select *
from goods
where id in (
    select goods_id
    from goodstore
    where store_id in (select id from store where name in ('Склад1', 'Склад2', 'Склад3') )
    group by goods_id
    having count(distinct store_id) = 3
)
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance

Последний раз редактировалось pproger; 27.07.2011 в 01:43.
pproger вне форума Ответить с цитированием
Старый 27.07.2011, 09:20   #4
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Цитата:
2Serge_Bliznykov
cross join... жесть))
pproger, простите, не уловил смысл комментария...
Можно поподробнее, что именно не понравилось/что не будет работать?

На самом деле, ни мой, ни Ваш запрос не решает ту задачу, которую хочет автор топика. (я специально выделил в своём сообщении "есть на всех трёх складах")
А ему хотелось бы видеть товар, который есть на двух складах из трёх (например, на втором и третьем)...

Я могу написать такой запрос... если надо...
НО!

1) я полностью согласен с тем, что структура БД НЕПРАВИЛЬНАЯ.
Если есть возможность - меняйте, пока не поздо!!

2) ну и неплохо бы знать целевую СУБД (могут быть нюансы.. например, можно ли использовать CASE ... )
Serge_Bliznykov вне форума Ответить с цитированием
Старый 27.07.2011, 11:02   #5
pproger
C++ hater
Старожил
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

2Serge_Bliznykov
Цитата:
Можно поподробнее, что именно не понравилось/что не будет работать?
а чего не понятно то? я же написал - кроссджоин. работать то будет, но очень медленно. разумеется, на более-менее внушительных таблицах. да и вообще, никогда так писать не стоит. тыж не пихаешь везде подряд bubble sort только из за того, что массивы небольшие?

Цитата:
На самом деле, ни мой, ни Ваш запрос не решает ту задачу, которую хочет автор топика.
да мне параллельно если честно, что хочет автор топика я привел просто привел нормальную альтернативу твоему кроссджоину.

Цитата:
А ему хотелось бы видеть товар, который есть на двух складах из трёх (например, на втором и третьем)...
не вопрос
Код:
select *
from goods
where id in (
    select goods_id
    from goodstore
    where store_id in (select id from store where name in ('Склад1', 'Склад2', 'Склад3') )
    group by goods_id
    having count(distinct store_id) = 2
)
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance

Последний раз редактировалось pproger; 27.07.2011 в 11:04.
pproger вне форума Ответить с цитированием
Старый 27.07.2011, 11:43   #6
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Цитата:
а чего не понятно то? я же написал - кроссджоин. работать то будет, но очень медленно. разумеется, на более-менее внушительных таблицах.
а.. понял. Никакого "кроссджойна" я тут не вижу.
Нормальная связь между тремя таблицами.
И работать будет отнюдь НЕ МЕДЛЕННО. (я только что проверил на таблицах с 10 тысячами записей, в выборке примерно полмиллиона записей(почем так много - отдельный вопрос). Oracle. первая выборка 0.175 секунды, вторая выборка этим же запросом (оракл закешировал) - 0.09 секунды)
Разумеется, связь по текстовому полю и, разумеется, никаких индексов нет.
Вашим запросом - первая выборка 0.12 секунды, после кеширования - 0.06 секунды)

проблема в том, что ваш вариант запроса с EXIST - это СОВСЕМ другой запрос!
Ну, например, Вы таким образом не получите количество товара на втором и третьем складах...

Цитата:
да мне параллельно если честно, что хочет автор топика я привел просто привел нормальную альтернативу твоему кроссджоину.
ну, исходя из вышесказанного - это НЕ альтернатива. Это просто СОВСЕМ другой запрос.


Ладно. я понял Вашу позицию... думаю, диспут продолжать бессмысленно...

Последний раз редактировалось Serge_Bliznykov; 27.07.2011 в 11:45.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 27.07.2011, 14:42   #7
pproger
C++ hater
Старожил
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

2Serge_Bliznykov
Цитата:
а.. понял. Никакого "кроссджойна" я тут не вижу.
а я вижу.

Цитата:
select * from Table1, Table2, table3
where Table1.Tovar = Table2.Tovar
and Table2.Tovar = Table3.Tovar
какой будет результат? правильно, декартово произведение. поэтому ты и получил поллимона записей
Цитата:
Наконец, cross join. Этот тип join еще называют декартовым произведением (на английском - cartesian product). Настоятельно рекомендую использовать его с умом, так как время выполнения запроса с увеличением числа таблиц и строк в них растет по экспоненте.
пруфец: http://www.javenue.info/post/20

Цитата:
Ну, например, Вы таким образом не получите количество товара на втором и третьем складах...
откуда новые условия взялись. ты сам поставил задачу (привел пример для автора) как
Цитата:
а по сути вопроса.
чтобы найти товар, который есть на всех трёх складах достаточно написать:
я просто привел более удачную реализацию ЭТОЙ задачи
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance
pproger вне форума Ответить с цитированием
Старый 27.07.2011, 15:06   #8
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

Цитата:
какой будет результат? правильно, декартово произведение. поэтому ты и получил поллимона записей
ну разумеется, я получил столько записей, потому как поле TOVAR (у меня наименование объекта) НЕ УНИКАЛЬНОЕ!. Разумеется, все неуникальные значения УМНОЖИЛИСЬ.

Цитата:
Наконец, cross join. Этот тип join еще называют декартовым произведением (на английском - cartesian product). Настоятельно рекомендую использовать его с умом, так как время выполнения запроса с увеличением числа таблиц и строк в них растет по экспоненте.
ЕЩЁ раз повторяю.
Данный запрос НЕ ЯВЛЯЕТСЯ CROSS JOIN
это INNER JOIN, если уж терминология с JOIN Вам ближе!

Декартово произведение даст нам количество записей равное перемножению числу записей всех таблиц, участвующих в запросе, если для них НЕ УКАЗАНО поле связи.
например,
т.е. если в таблице 1 - 2 записи
в таблице 2 - 5 записей
и в таблице 3 - 4 записи
то в результате запроса:
Код:
select * from table1, table2, table3
Вы всегда получите 2*5*4 = 40 записей.

в результате же запроса
Код:
select * from Table1, Table2, table3
where Table1.Tovar = Table2.Tovar
and Table2.Tovar = Table3.Tovar
вы получите столько записей, сколько товаров СОВПАДАЕТ в трёх разных складах
Если одинаковый товар будет ОДИН, то в результаете будет ОДНА запись в результирующем запросе.
ИЛИ НИ ОДНОГО, если товары в разных таблицах все будут отличаться.
Где Вы здесь увидели декартово произведение?!!
Но, разумеется, поле TOVAR должно быть ИДЕНТИФИЦИРУЮЩИМ (т.е. уникальным в пределах одной таблицы).

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



Цитата:
откуда новые условия взялись. ты сам поставил задачу (привел пример для автора) как
ладно. я Вас понял. ниоткуда не взялись.
Пусть Автор разберается, что ему нужно и что он хочет получить
Serge_Bliznykov вне форума Ответить с цитированием
Старый 28.07.2011, 20:41   #9
Macklay
Пользователь
 
Аватар для Macklay
 
Регистрация: 27.06.2009
Сообщений: 30
По умолчанию

Огромное спасибо господа, pproger и Serge_Bliznykov!!! В вашей дискуссии я увидел очень полезные для своей задачи и для себя в частности мысли и способы реализации..
Таблицы и правда кривые, но использовать нужно именно так без ключевого поля, а если даже оно и есть то в пределах одной таблицы.. А также внутри одной таблицы тоже могут быть двойники с разными ID.. Поэтому с целью полного исключения дублирующихся записей могу полагаться только на "Наименование"..
P.S. Ещё раз благодарю, очень приятно получить помощь и "услышать" мнение таких замечательных специалистов! А также, отдельное спасибо, создателям этого полезного и удобного форума!

Проблему с поиском двойников решил)
Теперь ситуация обстоит так:

Sklad | Tovar
Склад_1 | Карандаш
Склад_2 | Карандаш
------------------
Склад_3 | Ластик
Склад_1 | Ластик
------------------
Склад_1 | Линейка
Склад_2 | Линейка
------------------
........................
Склад_n | Ручка
Склад_m | Ручка

Складов n-ое количество... Задача посчитать сколько общих двойников у каждой пары складов...

И (или) вывести их в таком виде:
Склад_n Склад_m - общее количество двойников
Пример:
Склад_1 Склад_2 - 2

Благодарю за любую помощь или совет...

Последний раз редактировалось Stilet; 29.07.2011 в 07:39.
Macklay вне форума Ответить с цитированием
Старый 29.07.2011, 07:09   #10
Neymexa
Proffesional
Форумчанин
 
Аватар для Neymexa
 
Регистрация: 18.11.2008
Сообщений: 417
По умолчанию

Цитата:
Сообщение от Macklay Посмотреть сообщение
Задача посчитать сколько общих двойников у каждой пары складов...


Благодарю за любую помощь или совет...
не совсем понял, что значит поиск двойников. Может тебе стоит прочитать про group by?
О, степь родимая, как я скучаю по тебе...
Neymexa вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Поиск совпадений Claster Общие вопросы Delphi 4 22.06.2011 17:34
Поиск совпадений в ListBox NiKiToZZ- Помощь студентам 7 05.01.2011 10:54
Поиск совпадений в БД _PROGRAMM_ PHP 6 21.05.2010 13:53
Поиск данных в нескольких таблицах a_n_n_a БД в Delphi 10 23.04.2010 11:33
Поиск совпадений mistx Microsoft Office Excel 22 14.08.2009 13:41