Модераторы: skyboy
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Подсчет одним запросом. Возможно ли? PostgreSQL 9.3.1 
:(
    Опции темы
Majestio
Дата 28.10.2014, 11:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 83
Регистрация: 19.12.2010

Репутация: нет
Всего: нет



Доброго времени суток!

В процессе разработки отчета возникла задача относительно "хитрого" подсчета. Время поджимало - решил тремя запросами и частичным расчетом на клиенте. Но чувствую, то ли практики не хватает с SQL, то ли воображения. Посему, прошу ликбеза.

Усеченная структура БД
user posted image

Clients - хранит карточки клиентов
Service - хранит карточки обслуживаний
Service2Clients - хранит связки клиентов и обслуживаний (многие-к-многим)
RubricaNames - хранит каталог рубрикаторов
Rubricator - хранит рубрики по всем рубрикаторам
Points2Rubrica - хранит привязки значений по рубрикам к различным сущностям БД (например, к обслуживаниям)

Задача

Найти количество обслуживаний клиентов за период по группе рубрикаторов.

Моя неправильная реализация

Код
SELECT r."Name", COUNT(s."Id") AS "Cnt" FROM (
  SELECT rn."Id", rn."Name" FROM public."RubricaNames" AS rn
  WHERE rn."Id" IN (90,91,92,93,94,134)
  ORDER BY rn."Name"
) AS r
LEFT OUTER JOIN  public."Rubricator" AS ru ON ru."GroupId" = r."Id"
LEFT OUTER JOIN  public."Points2Rubrica" AS pr ON pr."Rubrica" = ru."Id"
LEFT OUTER JOIN (SELECT * FROM public."Service" AS sv WHERE sv."Date" >= '2011-09-01' AND sv."Date" <= '2014-09-01') AS s ON s."Id" = pr."Point"
GROUP BY r."Id",r."Name"
ORDER BY r."Name"

Результат

user posted image

Неправильно следующее

  1. Цифры тут получаются недостоверные, т.к. считается не все. Подсчет идет по обслуживаниям, а не по обслуженным клиентам. Так как есть вероятность обслуживания группы - одно обслуживание на группу клиентов
  2. Не хватает одной строчки, в которой указано количество обслуживаний за указанный период без привязанных рубрикаторов по данной совокупности перечисленных рубрикаторов

Вообщем ... вот, ай нид хелп!
PM MAIL WWW   Вверх
Zloxa
Дата 29.10.2014, 09:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(Majestio @  28.10.2014,  12:07 Найти цитируемый пост)
Цифры тут получаются недостоверные, т.к. считается не все. Подсчет идет по обслуживаниям, а не по обслуженным клиентам. Так как есть вероятность обслуживания группы - одно обслуживание на группу клиентов

считайте count(distinct клиент.id)
Цитата(Majestio @  28.10.2014,  12:07 Найти цитируемый пост)
Не хватает одной строчки, в которой указано количество обслуживаний за указанный период без привязанных рубрикаторов по данной совокупности перечисленных рубрикаторов

rollup?

Это сообщение отредактировал(а) Zloxa - 29.10.2014, 09:08


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
baldina
Дата 29.10.2014, 11:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 2
Всего: 101



Zloxa, зачем distinct, ведь будет группировка?

вообще
Цитата(Zloxa @  29.10.2014,  09:08 Найти цитируемый пост)
клиент.id

это неправильно, т.к. даст число клиентов, а не их обслуживаний. нужно считать число в Service2Clients

Цитата(Majestio @  28.10.2014,  11:07 Найти цитируемый пост)
Не хватает одной строчки, в которой указано количество обслуживаний за указанный период без привязанных рубрикаторов 

JOIN делать на все сервисы, а не все рубрикаторы

что-то типа
Код

SELECT
 r.Name, COUNT(s.*) from Service2Clients AS s
INNER JOIN Service AS sv ON sv.Id = s.Service
LEFT OUTER JOIN Points2Rubrica AS pr ON pr.Point = sv.Id
LEFT OUTER JOIN  Rubricator AS ru ON pr.Rubrica = ru.Id
LEFT OUTER JOIN  (SELECT * FROM RubricaNames WHERE Id IN (90,91,92,93,94,134)) r ON r.Id=ru.GroupId
WHERE 
  sv.Date BETWEEN ('2011-09-01' AND <= '2014-09-01')
GROUP BY r.Name



PM MAIL   Вверх
Zloxa
Дата 29.10.2014, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(baldina @  29.10.2014,  12:10 Найти цитируемый пост)
Zloxa, зачем distinct, ведь будет группировка?

не просто distinct, а что нинаесть count(distinct <expression>). Чтобы посчитать не количество определенных(not null) идентифиакторов, как это сделает просто сount, а количество уникальных идентификаторов клиента в группе.

Добавлено через 3 минуты и 52 секунды
Цитата(baldina @  29.10.2014,  12:10 Найти цитируемый пост)
это неправильно, т.к. даст число клиентов, а не их обслуживаний

ну так а что тс пишет? ТС пишет что ему и нужны клиенты а не осблуживания - нет?
Цитата(Majestio @  28.10.2014,  12:07 Найти цитируемый пост)
Цифры тут получаются недостоверные, т.к. считается не все. Подсчет идет по обслуживаниям, а не по обслуженным клиентам.


Добавлено через 7 минут и 20 секунд
ну хотя, да, согласен. Не вник, не подумал, просто тыкнул пальцем в нёбо. 
Вникать, думать буду когда досуг настанет.


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
baldina
Дата 29.10.2014, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 2
Всего: 101



Цитата(Zloxa @  29.10.2014,  11:18 Найти цитируемый пост)
 count(distinct <expression>)

понял, спс. хотя в данном случае кажется нет разницы, т.к. Service2Clients очевидно имеет primary key (Client, Service), и именно эта (никогда не нулевая) комбинация и интересует ТС в запросе 
PM MAIL   Вверх
Majestio
Дата 29.10.2014, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 83
Регистрация: 19.12.2010

Репутация: нет
Всего: нет



Вот такая штука вощем вымучалась:

Код

    SELECT rn."Name", COUNT(sc."Client")
      FROM public."RubricaNames" AS rn
      LEFT JOIN public."Rubricator" AS ru ON ru."GroupId" = rn."Id"
      LEFT JOIN public."Points2Rubrica" AS pr ON pr."Rubrica" = ru."Id"
      LEFT JOIN public."Service" AS sv ON sv."Id" = pr."Point" AND sv."Date" BETWEEN '2011-09-01' AND '2014-09-02'
      LEFT JOIN public."Service2Clients" AS sc ON sc."Service" = sv."Id"
      WHERE rn."Id" IN (90,91,92,93,94,134)
      GROUP BY rn."Id", rn."Name"
      ORDER BY rn."Name"

PM MAIL WWW   Вверх
baldina
Дата 29.10.2014, 17:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 2
Всего: 101



Цитата(Majestio @  29.10.2014,  17:12 Найти цитируемый пост)
Вот такая штука вощем вымучалась:

а как же
Цитата(Majestio @  28.10.2014,  11:07 Найти цитируемый пост)
Не хватает одной строчки, в которой указано количество обслуживаний за указанный период без привязанных рубрикаторов по данной совокупности перечисленных рубрикаторов

?
PM MAIL   Вверх
Majestio
Дата 29.10.2014, 18:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 83
Регистрация: 19.12.2010

Репутация: нет
Всего: нет



Потом добавил ...
Код

UNION
SELECT '═ не указано ═', 
    (SELECT COUNT(*) FROM public."Service" AS sv WHERE sv."Date" BETWEEN '2011-09-01' AND '2014-09-02') -
    (SELECT SUM(s."Cnt") FROM ( 
     ..........................

Понимаю, что не совсем по фэншую - время горит.
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.0481 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.