Подзапросы SQL, чтобы попытаться получить максимальную разницу одного и того же столбца в двух таблицах - PullRequest
2 голосов
/ 12 января 2010

Я хочу получить максимальное расхождение между двумя таблицами в день на один идентификатор.У меня есть следующие данные в базе данных mysql

insert into test.foo values ('2010-01-10', 1, 10);
insert into test.foo values ('2010-01-10', 1, 5);
insert into test.foo values ('2010-01-10', 2, 10);
insert into test.foo values ('2010-01-10', 2, 10);
insert into test.foo values ('2010-01-10', 3, 15);
insert into test.foo values ('2010-01-10', 3, 15);
insert into test.foo values ('2010-01-11', 1, 5);
insert into test.foo values ('2010-01-11', 1, 5);
insert into test.foo values ('2010-01-11', 2, 5);
insert into test.foo values ('2010-01-11', 2, 5);
insert into test.foo values ('2010-01-11', 3, 5);
insert into test.foo values ('2010-01-11', 3, 5);

insert into test.bar values ('2010-01-10', 1, 5);
insert into test.bar values ('2010-01-10', 1, 5);
insert into test.bar values ('2010-01-10', 2, 5);
insert into test.bar values ('2010-01-10', 2, 5);
insert into test.bar values ('2010-01-10', 3, 5);
insert into test.bar values ('2010-01-10', 3, 5);
insert into test.bar values ('2010-01-11', 1, 10);
insert into test.bar values ('2010-01-11', 1, 10);
insert into test.bar values ('2010-01-11', 2, 5);
insert into test.bar values ('2010-01-11', 2, 5);
insert into test.bar values ('2010-01-11', 3, 5);
insert into test.bar values ('2010-01-11', 3, 5);

Вот мой запрос:

SELECT t1.`date`, t1.id, t1.sums, t2.sums, max(t1.sums - t2.sums) FROM
  (select `date`, id, sum(val) sums
   from test.foo
   group by `date`, id) as t1,
  (select `date`, id, sum(val) sums
   from test.bar
   group by `date`, id) as t2
WHERE t1.`date` = t2.`date` AND t1.id = t2.id
group by t1.`date`

Я получаю такой результат:

+---------------------+----+------+------+------------------------+
| date                | id | sums | sums | max(t1.sums - t2.sums) |
+---------------------+----+------+------+------------------------+
| 2010-01-10 00:00:00 |  1 |   15 |   10 |                     20 |
| 2010-01-11 00:00:00 |  1 |   10 |   20 |                      0 |
+---------------------+----+------+------+------------------------+
2 rows in set (0.00 sec)

I 'я хотел бы получить этот результат: я получаю этот результат:

+---------------------+----+------+------+------------------------+
| date                | id | sums | sums | max(t1.sums - t2.sums) |
+---------------------+----+------+------+------------------------+
| 2010-01-10 00:00:00 |  1 |   15 |   10 |                     20 |
| 2010-01-11 00:00:00 |  2 |   10 |   10 |                      0 |  <----- 
+---------------------+----+------+------+------------------------+

Кто-нибудь может мне помочь?Я хотел бы получить максимальную разницу, а затем линию, которая сопровождала ее.Этот запрос дает мне правильную разницу, но не идентификатор и суммы, которые идут с ним.Коллега предложил также группировать по идентификатору, но, как я думал, это просто выровняло результат, и каждый идентификатор был указан вместо одного идентификатора за день, который имел максимальную разницу.

Большое спасибо заранее

Ответы [ 3 ]

1 голос
/ 12 января 2010

Этот должен работать для вас.

Сортирует суммы в порядке убывания, присваивая им звание, а затем получает только те, которые имеют ранг = 1.

SELECT id, `date`, sums FROM (
  SELECT id, `date`, sums,
  CASE
    WHEN @d != `date` THEN @rownum := 1 
    ELSE @rownum := @rownum + 1
  END AS rank,
  @d := `date`
FROM
(
  SELECT t1.`date`, t1.id, t1.sums t1_sums, t2.sums t2_sums, (t1.sums - t2.sums) sums
  FROM
    (select `date`, id, sum(val) sums
     from foo
     group by `date`, id) as t1,
    (select `date`, id, sum(val) sums
     from bar
     group by `date`, id) as t2,
     (SELECT @rownum := 0, @d := NULL) r
  WHERE t1.`date` = t2.`date` AND t1.id = t2.id
  GROUP BY t1.`date`, t1.id, t2.`date`, t2.id
  ORDER BY t1.`date`, (t1.sums - t2.sums) DESC, t1.id
  ) x
) y
WHERE rank = 1
1 голос
/ 12 января 2010
SELECT t1.`date`, t1.id, t1.sums, t2.sums, max(t1.sums - t2.sums) FROM
  (select `date`, id, sum(val) sums
   from test.foo
   group by `date`, id) as t1,
  (select `date`, id, sum(val) sums
   from test.bar
   group by `date`, id) as t2
WHERE t1.`date` = t2.`date` AND t1.id = t2.id
group by t1.`date`

Во внешнем запросе вы группируете по дате, а не по идентификатору, таким образом, вы не получаете ожидаемый идентификатор. Если вы хотите найти идентификатор, связанный с наибольшим расхождением, то сначала вам нужно найти наибольшую дискретность, а затем используйте другой запрос, чтобы выяснить, какие идентификаторы (или идентификаторы) связаны с этим. Вам придется решить, что вы хотите делать с дубликатами. Как то так (не проверено) ...

SELECT t3.`date`, t3.id, t3.diff
  (SELECT t1.`date`, t1.id, t1.sums, t2.sums, max(t1.sums - t2.sums) as diff FROM
    (select `date`, id, sum(val) sums
     from test.foo
     group by `date`, id) as t1,
    (select `date`, id, sum(val) sums
     from test.bar
     group by `date`, id) as t2
  WHERE t1.`date` = t2.`date` AND t1.id = t2.id) as t3
WHERE t3.diff = (correlated subquery to get maximum value of diff for each date)

Или используйте отдельные запросы.

0 голосов
/ 12 января 2010

Вывод следующего запроса:

+----------+- ---+------+------+-------+
|date      |id   |sumf  |sumb  |maxdiff|
+----------+- ---+------+------+-------+
|2010-01-10|    1|    30|    20|     10|
|2010-01-10|    2|    40|    20|     20|
|2010-01-10|    3|    60|    20|     40|
|2010-01-11|    1|    20|    40|     20|
|2010-01-11|    2|    20|    20|      0|
|2010-01-11|    3|    20|    20|      0|
+----------+- ---+------+------+-------+


select m.date, m.id, s.sumf, s.sumb, m.maxdiff
from (
    --subquery2: get the maximum different absolute sum between foo and bar for each date/id combination
    select s.date, s.id, max(abs(s.sumf - s.sumb)) as maxdiff
    from (
        --subquery1: get the sum of values for each date/id combination
        select f.date, f.id, sum(f.val) as sumf, sum(b.val) as sumb
        from foo f
        inner join bar b on f.date = b.date and f.id = b.id
        group by f.date, f.id
    ) s
    group by s.date, s.id
) m 
--join back against subquery1 to find out which sums gave us the max difference
inner join (
    select f.date, f.id, sum(f.val) as sumf, sum(b.val) as sumb
    from foo f
    inner join bar b on f.date = b.date and f.id = b.id
    group by f.date, f.id
) s on m.date = s.date and m.id = s.id and m.maxdiff = abs(s.sumf - s.sumb)

Примечание: это вернет более одной строки в случае дублирования maxdiff s, где подлежащие вычитанию суммы имеют разные значения. Я считаю, что это правильное поведение, если вы должны вернуть sumf и sumb, в противном случае вы не обязательно получите значения, которые создали maxdiff.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...