Сложный для меня запрос. Помогите, пожалуйста, найти решение

SQL во всех проявлениях - от ANSI-92 до TSQL.

Модераторы: Yurich, Absurd

GOS
Сообщения: 111
Зарегистрирован: 17 фев 2004, 10:32
Контактная информация:

25 сен 2004, 11:49

Для сбора статистики о расходе товара используется сл. запрос:
SELECT ZD_BID, B_NAZV, B_AVT, SUM(ZD_CNT) FROM Book, Zakaz_M, Zakaz_D WHERE (ZM_ID=ZD_ZID) AND
(ZM_DATA_SOZD BETWEEN '01.01.2004' AND '31.12.2004') AND (B_ID=ZD_BID) GROUP BY ZD_BID, B_NAZV, B_AVT

Где ZD_BID- код товара в детальной таблице
ZD_CNT- кол-во товара по позиции в детальной таблице
ZD_ZID- Поле для связи тетальной таблицы с главной
ZM_ID-идентификатор позиции в главной таблице
ZM_DATA_SOZD - дата создания заказа

Book-таблица товаров
Zakaz_M, Zakaz_D-гл. и детальная таблицы розничных заказов.
ZakazO_M, ZakazO_D-гл. и детальная таблицы оптовых заказов.

Где имена полей по опт. таблицам:
ZOD_BID- код товара в детальной таблице
ZOD_CNT- кол-во товара по позиции в детальной таблице
ZOD_ZOMID- Поле для связи тетальной таблицы с главной
ZOM_ID-идентификатор позиции в главной таблице
ZOM_DATA_SOZD - дата создания заказа

Теперь надо в результат встваить ещё одну колонку по оптовым заказам, только как я не писал запросы не выходит корректного :(
Подскажите пожалуйста возможно ли реализовать такой запрос или
придётся строить временную таблицу и несколькими запросами загонять туда данные.
chur
Сообщения: 195
Зарегистрирован: 17 фев 2004, 10:44
Откуда: Riga, Latvia

25 сен 2004, 13:23

Попробуй объединить запросы в один с помощью UNION:
SELECT ZD_BID, B_NAZV, B_AVT, SUM(ZD_CNT) FROM Book, Zakaz_M, Zakaz_D WHERE (ZM_ID=ZD_ZID) AND
(ZM_DATA_SOZD BETWEEN '01.01.2004' AND '31.12.2004') AND (B_ID=ZD_BID) GROUP BY ZD_BID, B_NAZV, B_AVT
UNION
SELECT ZOD_BID, B_NAZV, B_AVT, SUM(ZOD_CNT) FROM Book, ZakazO_M, ZakazO_D WHERE (ZOM_ID=ZOD_ZOMID) AND
(ZOM_DATA_SOZD BETWEEN '01.01.2004' AND '31.12.2004') AND (B_ID=ZOD_BID) GROUP BY ZOD_BID, B_NAZV, B_AVT

Правда, встанет вопрос определения какая запись из какой таблицы.

P.S. Какой SQL диалект? Почему не используется JOIN.
Аватара пользователя
AiK
Сообщения: 2271
Зарегистрирован: 13 фев 2004, 18:14
Откуда: СПб
Контактная информация:

25 сен 2004, 14:50

Правда, встанет вопрос определения какая запись из какой таблицы.
Это элементарно, Ватсон, если добавить фейковую колонку

Код: Выделить всё

select 1 as 'fake', ...
union all
select 2 as 'fake', ...
Какой SQL диалект
ANSI 92 :)
Почему не используется JOIN
Используются. Знаки равенства там неспроста стоят :) . Если честно, то такая нотация гораздо читабельнее, чем join.. on...
Даже самый дурацкий замысел можно воплотить мастерски
Аватара пользователя
AiK
Сообщения: 2271
Зарегистрирован: 13 фев 2004, 18:14
Откуда: СПб
Контактная информация:

25 сен 2004, 15:00

GOS, мне очень лениво вникать в твой вопрос, но у тебя должно быть что-то вроде этого :

Таблицы обзову
MAIN, OPT, DETAIL
у всех у них первичный ключ в каждой обзову одинаково order_id, а количество - cnt (хотя лучше qnt от quantity :) )

Тогда твой запрос будет выглядеть так:

Код: Выделить всё



select 

    m.order_id,
    sum (o.cnt) as 'opt',
    sum (d.cnt) as 'det'

from

    MAIN m,
    OPT o,
    DETAIL d

where

    m.order_id = o.order_id
and m.order_id = d.order_id
and ...

group by m.order_id
Даже самый дурацкий замысел можно воплотить мастерски
GOS
Сообщения: 111
Зарегистрирован: 17 фев 2004, 10:32
Контактная информация:

25 сен 2004, 21:44

Диалект первый. Используется связка Paradox-BDE-TQuery

Огромное спасибо всем за ответы!!!
Сейчас попробую выполнить, о ресультатах сообщю чуть позже...
GOS
Сообщения: 111
Зарегистрирован: 17 фев 2004, 10:32
Контактная информация:

25 сен 2004, 23:22

Результаты такие:
При использовании единого запроса сл. ситуация: если по оптовым таблицам(Master-Detail) и розничным таблицам(Master-Detail) получается различное число пунктов то в колонке соответствующей меньшему чилслу пунктов записи дублируются и как следствие сумма не верна.

Если использовать объединения типа UNION то статистика корректна, но строка по опту следует за строкой по рознице, а мне их надо разнести по колонкам...

У самого пока не получается... :(
Уважаемые, что подскажете ?

AiK, а что за "фейковые" колонки?
Аватара пользователя
AiK
Сообщения: 2271
Зарегистрирован: 13 фев 2004, 18:14
Откуда: СПб
Контактная информация:

26 сен 2004, 00:13

"фейковые"
я ж писал fake - мог бы и в словарь заглянуть :) fake = финт. Многие отчётники умеют такие результаты разворачивать.

Я пока твою структуру данных не догнал. У тебя 4 таблицы. В главных таблицах есть только ID заказа и дата исполнения,
а в детальных таблицах - ID заказа, ID товара и его количество, так? А узнать ты хочешь сколько товара продали оптом и в розницу за период времени, так?
Даже самый дурацкий замысел можно воплотить мастерски
chur
Сообщения: 195
Зарегистрирован: 17 фев 2004, 10:44
Откуда: Riga, Latvia

26 сен 2004, 00:48

По поводу JOIN. Насколько я понимаю механизм SQL то это выглядит так. При запросе типа FROM t1, t2, t3 генерируется количество записей равное произведению числа записей в каждой таблице, которые проверяются на соответствие WHERE. Т.е. при 100 записях в каждой таблице получается 1 млн. записей, которые надо, в данном случае, проверить по трем условиям. При запросе с использованием JOIN генерируется количество записей равное количеству записей в таблице с наибольшим их количеством (почти по-русски :) ). T.e 100 записей, и проверить их надо будет по одному условию.
Аватара пользователя
AiK
Сообщения: 2271
Зарегистрирован: 13 фев 2004, 18:14
Откуда: СПб
Контактная информация:

26 сен 2004, 04:29

GOS, боюсь, что твоя задачка в один запрос неразрешима.
Более точно, я не знаю как решить эту задачку в Paradox'e одним запросом.
OUTER JOIN очень близко, см. например такой запрос:

Код: Выделить всё

select 
  ZD_BID,
  ZOD_BID,
  ZD_CNT,
  ZOD_CNT	 
from 
    Zakaz_D 
  full outer join  ZakazO_D 
on   ZD_BID = ZOD_BID
(суммирование не использую, чтобы ты понял о чём речь)

Можно поэксперементировать с LEFT и RIGHT JOIN'ами, но беда в том, что наряду с уникальными товарами, такие запрос строят ещё и все сочетания по совпадающим товарам.

Можно сделать выборку только по уникальным товарам (по опту и по рознице) т.е. по т.н. substract join и объеденить их с совпадающими товарами, но это опять не в одну строку запись будет. Так что можешь использовать временные таблицы.
Даже самый дурацкий замысел можно воплотить мастерски
chur
Сообщения: 195
Зарегистрирован: 17 фев 2004, 10:44
Откуда: Riga, Latvia

26 сен 2004, 05:52

Предлагаю результат после UNION сгруппировать еще раз.

Код: Выделить всё

SELECT Z, N, A, SUM(IIF(F=1, S, 0)) AS ROZN, SUM(IIF(F=2, S, 0)) AS OPT
FROM

(
SELECT ZD_BID AS Z, B_NAZV AS N, B_AVT AS A, SUM(ZD_CNT) AS S, 1 AS F FROM Book, Zakaz_M, Zakaz_D WHERE (ZM_ID=ZD_ZID) AND 
(ZM_DATA_SOZD BETWEEN '01.01.2004' AND '31.12.2004') AND (B_ID=ZD_BID) GROUP BY ZD_BID, B_NAZV, B_AVT 

UNION 

SELECT ZOD_BID AS Z, B_NAZV AS N, B_AVT AS A, SUM(ZOD_CNT) AS S, 2 AS F FROM Book, ZakazO_M, ZakazO_D WHERE (ZOM_ID=ZOD_ZOMID) AND 
(ZOM_DATA_SOZD BETWEEN '01.01.2004' AND '31.12.2004') AND (B_ID=ZOD_BID) GROUP BY ZOD_BID, B_NAZV, B_AVT 
)

GROUP BY Z, N, A
Ответить