Проблемы запроса с HAVING

anpv

Guest
Проблемы запроса с HAVING

Доброго времени суток.
PHP:
CREATE TABLE `table_master` (
  `id` int NOT NULL auto_increment,
...
  PRIMARY KEY (`id`)
);
CREATE TABLE `table_slave1` (
...
  `table_master_id` int NOT NULL,
  `price` decimal(10, 2) NOT NULL default '0.00'
...
);
CREATE TABLE `table_slave2` (
...
  `table_master_id` int NOT NULL,
  `price` decimal(10, 2) NOT NULL default '0.00'
...
);
Следующий запрос возвращает пустой результат, хотя должен вернуть непустой.
PHP:
SELECT 
  COUNT(*)
FROM
  `table_master` tm
  INNER JOIN `table_slave1` ts1 ON (ts1.`table_master_id` = tm.`id`)
  INNER JOIN `table_slave2` ts2 ON (ts2.`table_master_id` = tm.`id`)
HAVING
  (SUM(ts1.`price`) > SUM(ts2.`price`));
Подскажите пожалуйста в чем дело.
 

jer

...
почему должен? раз нет ошибок, то значит, что запрос возвращает то, что ты ЗАПРОСил.

и твоих данных мы не знаем.
 

anpv

Guest
jer
С данными все нормально.
Sad Spirit
GROUP BY не помогает
 

jer

...
дай пример с данными в несколько строчек и скажи на словах что ты хочешь посчитать...
 

anpv

Guest
jer
В таблице `table_slave1` содержатся суммы оплат по заказам содержащимся в таблице `table_master`
В таблице `table_slave2` (могут) содержатся оплаченные суммы по заказам содержащимся в таблице `table_master`
Я хочу подсчитать количество неоплаченных заказов.
Так вроде работает, но выдает неправильный результат
PHP:
SELECT
  COUNT(*)
FROM
  `table_master` tm
  INNER JOIN `table_slave1` ts1 ON (ts1.`table_master_id` = tm.`id`)
  LEFT JOIN `table_slave2` ts2 ON (ts2.`table_master_id` = tm.`id`)
HAVING
  (SUM(ts1.`price`) > SUM(ts2.`price`));
и с GROUP BY `table_master`.`id` запрос ничего не возвращает
 

jer

...
все правильно. - что не работает.

1-е. GROUP BY обязательно
2-е. надо смотреть кол-во возвращаемых строк
т.е.:
[sql]
SELECT count(*) FROM
(SELECT
COUNT(*)
FROM
`table_master` tm
INNER JOIN `table_slave1` ts1 ON (ts1.`table_master_id` = tm.`id`)
LEFT JOIN `table_slave2` ts2 ON (ts2.`table_master_id` = tm.`id`)
GROUP BY tm.`id`
HAVING
(SUM(ts1.`price`) > SUM(ts2.`price`))
)
[/sql]

либо, если mysql не поддерживает вложенные запросы, то юзай mysql_num_rows().
 

anpv

Guest
jer
Так ведь GROUP BY tm.`id` отсечет множественность значений ts1.`table_master_id` и ts2.`table_master_id`.
У меня связь таблиц:
PHP:
`table_master`(1) один => ко многим  `table_slave1`(1 .. n) и `table_slave2` (0 .. n)
Но даже с этим запросом ничего не выходит, он возвращает 0.
 

jer

...
Так ведь GROUP BY tm.`id` отсечет множественность значений ts1.`table_master_id` и ts2.`table_master_id`.
ничего он не отсечет.

покажи на каких данных этот запрос не работает...
 

chira

Новичок
anpv
сделай проверку:
Код:
SELECT 
  COUNT(*) cn, SUM(ts1.`price`) sm1, SUM(ts2.`price`) sm2
FROM `table_master` tm 
  INNER JOIN `table_slave1` ts1
    ON (ts1.`table_master_id` = tm.`id`)
  LEFT JOIN `table_slave2` ts2
    ON (ts2.`table_master_id` = tm.`id`)
GROUP BY tm.`id`
и посмотри на значения сумм ...
проверь с GROUP BY и без, с INNER и LEFT JOIN ...
 

anpv

Guest
chira
Запросы:
PHP:
SELECT COUNT(*) cn FROM
(SELECT 
  COUNT(*) cn, SUM(ts1.`price`) sm1, SUM(ts2.`price`) sm2 
FROM 
  `table_master` tm 
  INNER JOIN `table_slave1` ts1 ON (ts1.`table_master_id` = tm.`id`) 
  LEFT JOIN `table_slave2` ts2 ON (ts2.`table_master_id` = tm.`id`) 
  GROUP BY tm.`id`) sl
и:
PHP:
SELECT 
  COUNT(DISTINCT tm.`id`) cn
FROM
  `table_master` tm
  INNER JOIN `table_slave1` ts1 ON (ts1.`table_master_id` = tm.`id`)
  LEFT JOIN `table_slave2` ts2 ON (ts2.`table_master_id` = tm.`id`)
HAVING
  (SUM(ts1.`price`) > SUM(ts2.`price`));
возвращают одинаковый cn.
А последний ни в какую ни хочет работать с группировкой.

jer
Ну например такие данные:
`table_master`
`id`
1
2
3
`table_slave1`
`table_master_id` | `price`
1 | 5.00
1 | 10.00
2 | 1.00
2 | 2.00
2 | 3.00
3 | 15.00
`table_slave2`
`table_master_id` | `price`
1 | 7.00
1 | 8.00
3 | 14.00
В результате запроса должно получиться количество равное двум (1-й заказ оплачен полностью 7+8=5+10, 2-й вообще не оплачен 1+2+3 > 0, а 3-й не полностью оплачен 15 > 14)
 

jer

...
[sql]
SELECT tm.`id`, SUM( ts1.`price` ) s1, SUM(ts2.`price`) s2
FROM `table_master` tm
INNER JOIN `table_slave1` ts1 ON ( ts1.`table_master_id` = tm.`id` )
LEFT JOIN `table_slave2` ts2 ON ( ts2.`table_master_id` = tm.`id` )
GROUP BY tm.`id`
HAVING SUM( ts1.`price` ) > SUM(ts2.`price`)
[/sql]

на твоих данных дает:

id s1 s2
2 6 0
3 15 14

все верно.

у тебя что МОЙ запрос на ЭТИХ данных показывает?
 

anpv

Guest
Оказывается нужно было так:
Код:
SELECT 
  count(*) cn 
FROM 
  (SELECT 
    COUNT(*)
   FROM 
     `table_master` tm
     INNER JOIN `table_slave1` ts1 ON ( ts1.`table_master_id` = tm.`id` )
     LEFT JOIN `table_slave2` ts2 ON ( ts2.`table_master_id` = tm.`id` )
     GROUP BY tm.`id`
     HAVING (SUM( ts1.`price` ) > IFNULL(SUM( ts2.`price`), 0)));
HAVING не хотел сумму сравнивать с NULL.
 

jer

...
да, только об этом хотел тебе написать, а ты сам разобрался. ;)
 

anpv

Guest
При таких данных (и имеющихся см. выше 22.12.04 15:50):
[sql]
INSERT INTO `table_master` (`id`) VALUES (382);
INSERT INTO `table_slave1` (`table_master_id`, `price`) VALUES (382, 38400);
INSERT INTO `table_slave2` (`table_master_id`, `price`) VALUES (382, 34560);
INSERT INTO `table_slave2` (`table_master_id`, `price`) VALUES (382, 3840);
[/sql]
запрос:
[sql]
SELECT tm.`id`, sum(ts1.`price`), sum(ts2.`price`)
FROM `table_master` tm
INNER JOIN `table_slave1` ts1 ON (ts1.`table_master_id` = tm.`id`)
LEFT JOIN `table_slave2` ts2 ON (ts2.`table_master_id` = tm.`id`)
GROUP BY tm.`id`
HAVING (SUM(ts1.`price`) > IFNULL(SUM(ts2.`price`), 0))
[/sql]
выдает странный (неправильный ?) результат:
id | sum(ts1.price) | sum(ts2.price)
2 | 6.00 | NULL
3 | 15.00 | 14.00
382 | 76800.00 | 38400.00 -- ??????????????
Запрос, почемуто, посчитал 2 раза сумму по таблице `table_slave1`.
Подскажите, в чем дело???
 

jer

...
а, ну конечно %) "слона то я и не приметил..."

сделай:
[sql]SELECT *
FROM `table_master` tm
INNER JOIN `table_slave1` ts1 ON ( ts1.`table_master_id` = tm.`id` )
LEFT JOIN `table_slave2` ts2 ON ( ts2.`table_master_id` = tm.`id` )
[/sql]
и сам все поймешь...

наверно все таки придется отдельно считать суммы для стоимости и для оплаты, а потом сравнивать. это если цена товара будет составной. если же цена будет товара будет одной записью, то можно так:

[sql]SELECT tm.`id` , ts1.`price`, sum( ts2.`price` )
FROM `table_master` tm
INNER JOIN `table_slave1` ts1 ON ( ts1.`table_master_id` = tm.`id` )
LEFT JOIN `table_slave2` ts2 ON ( ts2.`table_master_id` = tm.`id` )
GROUP BY tm.`id`
HAVING (ts1.`price` > SUM( ts2.`price` ))
[/sql]
 

chira

Новичок
есть ещё вариант:
[SQL]
SELECT tm.`id`
, sum( ts1.`price` )*COUNT(DISTINCT ts1.id)/COUNT(*) sum1
, sum( IFNULL(ts2.`price`,0)) *COUNT(DISTINCT ts2.id)/COUNT(*) sum 2
FROM `table_master` tm
INNER JOIN `table_slave1` ts1 ON ( ts1.`table_master_id` = tm.`id` )
LEFT JOIN `table_slave2` ts2 ON ( ts2.`table_master_id` = tm.`id` )
GROUP BY tm.`id`
[/SQL]
 
Сверху