[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Не получается написать корректный запрос
greatilya
Имеется 4 таблицы...
Необходимо решить задачу 1 запросом.
user posted image

В результате должно получиться:
таблица содержащая всех клиентов, количество посещений, общая сумма покупок и т.д.
На 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 написал(а):
Решил задачу следующим способом:
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... ? а то выводятся все пользователи, даже которые не делали покупок...

Странный вопрос для человека, который сам ворочает такие запросы wink.gif

Должно работать условие "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, своё скромное спасибо отправил вам на Я.Деньги

Еще раз спасибо!
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.