Необходимо решить задачу 1 запросом.

В результате должно получиться:
таблица содержащая всех клиентов, количество посещений, общая сумма покупок и т.д.
На 1 строке 1 покупатель.
Вот что пишу:
SELECT
store.name AS "Магазин",
client.lastname AS "Фамилия",
client.firstname AS "Имя",
client.middlename AS "Отчество",
COUNT(trans.id) AS "Количество покупок",
COUNT(touch.client_id) AS "Количество посещений",
MAX(touch.moment) AS "Последнее посещение",
SUM(trans.price) AS "Сумма покупок"
FROM public.client
INNER JOIN public.trans ON client.id = trans.client_id
INNER JOIN public.store ON trans.store_id = store.id
INNER JOIN public.touch ON client.id = touch.client_id
WHERE (trans.purchase_date>'12.01.1900') AND (trans.purchase_date<'12.01.2020')
GROUP BY store.name, client.firstname, client.middlename, client.lastname
В итоге количество посещений в 78 раз больше чем на самом деле.
Если имеет значение, используется БД Postgree.
В чем я ошибся составляя запрос? Заранее признателен.
Спустя 15 минут, 17 секунд (29.03.2010 - 11:47) krasilich написал(а):
Здается мне что получение всех данных одним запросом в данной ситуации не самое оптимальное решение.
Делайте два запроса. Один на информацию по клиентам, другой на статистику.
Делайте два запроса. Один на информацию по клиентам, другой на статистику.
Спустя 16 минут, 5 секунд (29.03.2010 - 12:03) greatilya написал(а):
Два запроса сделать не могу, ибо ограничение Excel ... А одним вообще никак? может какой-то вложенный запрос можно замутить, или еще чего?
Спустя 19 минут, 4 секунды (29.03.2010 - 12:22) krasilich написал(а):
Если не сложно, можете выложить дамп базы в файле, попробую что-то придумать=)
Спустя 18 минут, 21 секунда (29.03.2010 - 12:40) greatilya написал(а):
Вот ссылка на дамб для Postgree: http://slil.ru/28872706
Такой вариант Вас устроит?
Такой вариант Вас устроит?
Спустя 1 час, 22 минуты, 17 секунд (29.03.2010 - 14:03) sergeiss написал(а):
Цитата (greatilya @ 29.03.2010 - 12:31) |
Если имеет значение, используется БД Postgree. |
Значение имеет, потому что у Постгре есть специфика синтаксиса, позволяющая выполнять сложные запросы за один заход.
Только структура запроса должна быть другая.
Попробуй вот такой запрос. Если пройдет - бум дальше думать
select client.lastname, client.firstname,
(select count(id) from trans where trans.id=client.id and purchase_date>'12.01.1900' AND purchase_date<'12.01.2020') as trans_count,
(select sum(price) from trans where trans.id=client.id where purchase_date>'12.01.1900' AND purchase_date<'12.01.2020' group by id) as sum_price
from client
Спустя 1 час, 13 минут, 57 секунд (29.03.2010 - 15:16) Guest написал(а):
Используй не INNER JOIN а OUTER JOIN
Спустя 14 часов, 25 минут, 6 секунд (30.03.2010 - 05:42) greatilya написал(а):
Цитата |
Попробуй вот такой запрос. Если пройдет - бум дальше думать |
Поправил запрос до такого:
select client.lastname, client.firstname,
(select count(id) from public.trans where trans.id=client.id and purchase_date>'12.01.1900' AND purchase_date<'12.01.2020') as trans_count,
(select sum(price) from public.trans where trans.id=client.id AND purchase_date>'12.01.1900' AND purchase_date<'12.01.2020' group by id) as sum_price
from client
т.к. ваш запрос не прошел, жаловался на WHERE в 3 строке.
На выходе запрос выдал всех трех покупателей но у всех количество покупок и сумма заказов по нулям. Хотя на самом деле у одного есть 11 покупок.
Спустя 7 минут, 59 секунд (30.03.2010 - 05:50) greatilya написал(а):
Цитата |
Используй не INNER JOIN а OUTER JOIN |
пробовал
OUTER JOIN public.trans ON client.id = trans.client_id
OUTER JOIN public.store ON trans.store_id = store.id
OUTER JOIN public.touch ON client.id = touch.client_id
выдает соответственно ошибку:
Цитата |
ERROR: syntax error at or near "OUTER" LINE 11: OUTER JOIN public.trans ON client.id = trans.client_id |
Если прописать так:
LEFT OUTER JOIN public.trans ON client.id = trans.client_id
LEFT OUTER JOIN public.store ON trans.store_id = store.id
LEFT OUTER JOIN public.touch ON client.id = touch.client_id
либо так:
RIGHT OUTER JOIN public.trans ON client.id = trans.client_id
RIGHT OUTER JOIN public.store ON trans.store_id = store.id
RIGHT OUTER JOIN public.touch ON client.id = touch.client_id
Результат идентичный что и при INNER JOIN
Спустя 49 минут, 7 секунд (30.03.2010 - 06:39) greatilya написал(а):
Решил задачу следующим способом:
Решил уменьшить сложность скрипта путем указания нужного магазина сразу в запросе.
А можно как-то убрать из запроса те записи у которых "touch_count" = 0... ? а то выводятся все пользователи, даже которые не делали покупок...
select (select name from public.store where id=2) as store_name,
client.lastname, client.firstname, client.middlename,
(select count(id) from public.trans where client_id=client.id and purchase_date>'12.01.1900' AND purchase_date<'12.01.2020' AND store_id=2) as trans_count,
(select sum(price) from public.trans where client_id=client.id AND purchase_date>'12.01.1900' AND purchase_date<'12.01.2020' AND store_id=2) as sum_price,
(select count(client_id) from public.touch where client_id=client.id and moment>'12.01.1900' AND moment<'12.01.2020') as touch_count,
(select max(moment) from public.touch where client_id=client.id and moment>'12.01.1900' AND moment<'12.01.2020') as touch_moment
from client order by trans_count desc
Решил уменьшить сложность скрипта путем указания нужного магазина сразу в запросе.
А можно как-то убрать из запроса те записи у которых "touch_count" = 0... ? а то выводятся все пользователи, даже которые не делали покупок...
Спустя 2 часа, 1 минута, 14 секунд (30.03.2010 - 08:40) sergeiss написал(а):
Цитата (greatilya @ 30.03.2010 - 07:39) |
А можно как-то убрать из запроса те записи у которых "touch_count" = 0... ? а то выводятся все пользователи, даже которые не делали покупок... |
Странный вопрос для человека, который сам ворочает такие запросы

Должно работать условие "where touch_moment>0", введенное сразу же после "from client".
И еще. Как скорость выполнения запроса? Там надо правильно расставить индексы.
И можно, кстати, вообще по-другому сам запрос построить, "красивее" его сделать.
А именно, вот так (пишу в упрощенном виде, только для подсчета количества и суммы покупок, чтобы показать принцип):
with
trans_count as (select client_id as id, count(id) as count_client_id from public.trans where purchase_date>'12.01.1900' AND purchase_date<'12.01.2020' AND store_id=2),
sum_price as (select client_id as id, sum(price) as sum_client_price from public.trans where purchase_date>'12.01.1900' AND purchase_date<'12.01.2020' AND store_id=2)
select id, count_client_id, sum_client_price
from client
full join trans_count
using( id )
full join sum_price
using( id )
Если я ничего не напутал, то должно сработать сразу же.
Суть такая:
сначала создаем временные таблицы trans_count и sum_price, где подсчитываем все количества и суммы соответственно, с привязкой к id клиента. А затем объединяем всё это через full join, используя поле id как связку.
Прошу обратить внимание - это именно один запрос, а не несколько подряд!!! Ключевое слово "with" - это часть синтаксиса.
И здесь также можно ограничить выборку, например, написав в самом конце "where sum_client_price>10" (или любое другое условие).
Спустя 1 час, 4 минуты, 14 секунд (30.03.2010 - 09:44) greatilya написал(а):
sergeiss
Огромное спасибо! Обязательно попробую предложенный Вами вариант, как только разберусь с Excel... при двух подставляемых параметрах он срабатывал нормально, а сейчас не хочет... либо параметры местами путает, либо длина запроса не нравится... вобщем с Excel разбираюсь...
sergeiss, своё скромное спасибо отправил вам на Я.Деньги
Еще раз спасибо!
Огромное спасибо! Обязательно попробую предложенный Вами вариант, как только разберусь с Excel... при двух подставляемых параметрах он срабатывал нормально, а сейчас не хочет... либо параметры местами путает, либо длина запроса не нравится... вобщем с Excel разбираюсь...
sergeiss, своё скромное спасибо отправил вам на Я.Деньги
Еще раз спасибо!