LINUX.ORG.RU

[sql] join multiple tables and sum

 


0

1

Допустим есть таблица в которой описаны люди. Также есть ссылающиеся таблицы 1:n содержащие допустим покупки. Как правильно составить запрос чтобы при большом количестве джойнов не двоились (и т.д.) суммы.

★★★

Реквестирую более внятное изложение проблемы.

С простым примером

1) таблиц, 2) данных, 3) запросов, дающих негодный результат

и требованиями к годному результату.

r_asian ★☆☆
()
Ответ на: комментарий от r_asian
CREATE TABLE IF NOT EXISTS `b` (
  `id_b` int(11) NOT NULL AUTO_INCREMENT,
  `p_id` int(11) NOT NULL,
  `a` int(11) NOT NULL,
  PRIMARY KEY (`id_b`)
) ENGINE=InnoDB  DEFAULT CHARSET=cp1251 AUTO_INCREMENT=9 ;


INSERT INTO `b` (`id_b`, `p_id`, `a`) VALUES
(1, 1, 100),
(2, 1, 101),
(3, 2, 200),
(4, 2, 201),
(5, 3, 300),
(6, 3, 301),
(7, 4, 400),
(8, 4, 401);


CREATE TABLE IF NOT EXISTS `c` (
  `id_b` int(11) NOT NULL AUTO_INCREMENT,
  `p_id` int(11) NOT NULL,
  `a` int(11) NOT NULL,
  PRIMARY KEY (`id_b`)
) ENGINE=InnoDB  DEFAULT CHARSET=cp1251 AUTO_INCREMENT=9 ;



INSERT INTO `c` (`id_b`, `p_id`, `a`) VALUES
(1, 1, 100),
(2, 1, 101),
(3, 2, 200),
(4, 2, 201),
(5, 3, 300),
(6, 3, 301),
(7, 4, 400),
(8, 4, 401);



CREATE TABLE IF NOT EXISTS `p` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `client` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=cp1251 AUTO_INCREMENT=7 ;



INSERT INTO `p` (`id`, `client`) VALUES
(1, 'иванов'),
(2, 'петров'),
(3, 'сидоров'),
(4, 'разин');



запросы:

SELECT *,sum(b.a),sum(c.a) FROM `p`
left join b on (p.id=b.p_id)
left join c on (p.id=c.p_id)
group by(id)

дважды суммируют

visual ★★★
() автор топика
Ответ на: комментарий от r_asian

ыыыы, я тоже так думал

а теперь представь что у тебя в одной из таблиц

INSERT INTO `c` (`id_b`, `p_id`, `a`) VALUES
(1, 1, 100),
(2, 1, 100),
(3, 2, 200),
(4, 2, 200),
(5, 3, 300),
(6, 3, 300),
(7, 4, 400),
(8, 4, 400);

visual ★★★
() автор топика
Ответ на: комментарий от visual

Да заюзай ты подзапросы. Тут либо SQL-камасутра, вроде

...
    sum(b.a )/count(DISTINCT b.id_b) , 
...

Либо для каждого человека подзапросом его счет подбивать.

r_asian ★☆☆
()
Ответ на: комментарий от r_asian

Спасибо за мнение, подожду, может ещё кто чего напишет. Потому как в реальной задаче запрос с 6 таблицами будет просто гигантский.

visual ★★★
() автор топика
Ответ на: комментарий от visual
SELECT p.client client ,sum(b.a) sum FROM b,p where p.id=b.p_id group by p.client
union all
SELECT p.client client ,sum(c.a) sum FROM c,p where p.id=c.p_id group by p.client
order by client
select 
   p.client client
  ,sum(e.a) sum
from 
  (SELECT p_id, a FROM b
    union all
   SELECT p_id, a FROM c) e,
  p
where
  p.id=e.p_id
group by p.client
order by client
select 
   p.client client
  ,bp.sum   sumb
  ,cp.sum   sumc
from 
  (SELECT p_id, sum(b.a) sum FROM b group by p_id) bp,
  (SELECT p_id, sum(c.a) sum FROM c group by p_id) cp,
  p
where
  p.id=bp.p_id
  and
  p.id=cp.p_id
order by client
anonymous
()
Ответ на: комментарий от visual

Потому как в реальной задаче запрос с 6 таблицами будет просто гигантский

С подзапросами, вариантов вообще масса, в том числе и достаточно компактных. Позвольте полюбопытствовать отчего именно через join всё это делать потребно?

r_asian ★☆☆
()
Ответ на: комментарий от r_asian

а есть другие варианты?

Суть проблемы:

Есть «пациенты», у этих пациентов есть какиелибо параметры которые должны хранится отдельно. Надо сотворить форму поиска «пациентов» по параметрам.

visual ★★★
() автор топика
Ответ на: комментарий от visual

Надо сотворить форму поиска «пациентов» по параметрам.

Я такие штуки реализую через подзапросы. Получается довольно компактно и читаемое. Плюс позволяет задействовать орм почти без костылей.

CHARSET=cp1251

А вот за такое надо гнать из профессии ссаными тряпками!

Apple-ch ★★
()
Ответ на: комментарий от Apple-ch

CHARSET=cp1251

А вот за такое надо гнать из профессии ссаными тряпками!

Если бы все работали по профессии...

visual ★★★
() автор топика
Ответ на: комментарий от visual

а есть другие варианты?

есть, только объясни, чем вложенные запросы не устраивают?

можно, например, создать одно толстое представление (явное или неявное) и уже из него селектить

anonymous
()
Ответ на: комментарий от anonymous

есть, только объясни, чем вложенные запросы не устраивают?

боюсь запутатся

про вьювы знаю, сейчас пробую

можно, например, создать одно толстое представление (явное или неявное) и уже из него селектить

visual ★★★
() автор топика
Ответ на: комментарий от visual

боюсь запутатся

вот и причина; если что-то нельзя просто и внятно обосновать, то значит оно не нужно! :)
неестественное требование/ограничение плодит только лишние костыли

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.