PDA

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



GOS
25.09.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
25.09.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
25.09.2004, 14:50
Правда, встанет вопрос определения какая запись из какой таблицы.
Это элементарно, Ватсон, если добавить фейковую колонку


select 1 as 'fake', ...
union all
select 2 as 'fake', ...



Какой SQL диалект
ANSI 92 :)


Почему не используется JOIN
Используются. Знаки равенства там неспроста стоят :). Если честно, то такая нотация гораздо читабельнее, чем join.. on...

AiK
25.09.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
25.09.2004, 21:44
Диалект первый. Используется связка Paradox-BDE-TQuery

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

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

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

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

AiK, а что за "фейковые" колонки?

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

Я пока твою структуру данных не догнал. У тебя 4 таблицы. В главных таблицах есть только ID заказа и дата исполнения,
а в детальных таблицах - ID заказа, ID товара и его количество, так? А узнать ты хочешь сколько товара продали оптом и в розницу за период времени, так?

chur
26.09.2004, 00:48
По поводу JOIN. Насколько я понимаю механизм SQL то это выглядит так. При запросе типа FROM t1, t2, t3 генерируется количество записей равное произведению числа записей в каждой таблице, которые проверяются на соответствие WHERE. Т.е. при 100 записях в каждой таблице получается 1 млн. записей, которые надо, в данном случае, проверить по трем условиям. При запросе с использованием JOIN генерируется количество записей равное количеству записей в таблице с наибольшим их количеством (почти по-русски :)). T.e 100 записей, и проверить их надо будет по одному условию.

AiK
26.09.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
26.09.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

AiK
26.09.2004, 14:18
chur, позволь поинтересоваться, в каком из Paradox'ов появилась возможность сделать выборку из другой выборки?
Сдаётся мне, что и IIF это из Access'a.

chur
26.09.2004, 21:01
Про Paradox ничего не скажу, не знаю, но через BDE организовать выборку из выборки, наверно, можно.
IIF конечно из Access'а, но в Paradox'е, я надеюсь, есть аналогичные конструкции.

Naeel Maqsudov
11.10.2004, 22:29
НЕТ в Paradox никакого IIF и близко не стояло! Очень бедно там со встроенными функциями....

Naeel Maqsudov
11.10.2004, 22:50
Предлагаю сделать так:



SELECT
B_ID, B_NAZV, B_AVT,
(SELECT SUM(ZD_CNT) FROM Zakaz_M,Zakaz_D
WHERE ZD_BID=B_ID and ZM_ID=ZD_ZID and
ZM_DATA_SOZD BETWEEN '01.01.2004' AND '31.12.2004'
),
(SELECT SUM(ZOD_CNT) FROM ZakazO_M,ZakazO_D
WHERE ZOD_BID=B_ID and ZOM_ID=ZOD_ZID and
ZOM_DATA_SOZD BETWEEN '01.01.2004' AND '31.12.2004'
)
FROM
Book
ORDER BY B_NAZV, B_AVT



Subquery форэва!!! :)