2015-12-08 2 views
0

Это структура из двух таблицMysql: РЕГИСТРИРУЙТЕСЬ 2 таблицы, один из SUM не является правильным

Таблица A

+----+-----+----+----------------------+--------------------+----------+ 
| id | ... |....| time_start   | time_end   | total | 
+----+-----+----+----------------------+--------------------+----------+ 
    1    2015-12-06 10:00:00 2015-12-06 12:00:00  200 
    2    2015-12-07 10:00:00 2015-12-07 12:00:00  300    

Таблица B

+----+----------+------+------+------+------+ 
| id | idTableA | val1 | val2 | val3 | val4 | 
+----+----------+------+------+------+------+ 
    1  1  10  10  10  10 
    2  1  10  10  10  10 
    3  2  10  10  10  10 

Цель состоит в следующем: с учетом time_start и time_end дата, отображение суммы сумм (таблица А) и от суммы val1, val2, val3, val4

Пример:

  • TIME_START = 2015-12-01 00 : 00: 00

  • time_end = 2015-12-30 23:59:59

Результат expecte д: сумма общих = 500, сумма Вала (1-4) = 120

Я попытался так:

$myquery = ""; 
$myquery .= "SELECT SUM(tableA.total) AS myTotal,"; 
$myquery .= "SUM(tableB.val1) + SUM(tableB.val2) + SUM(tableB.val3) + SUM(tableB.val4) AS myValTotal "; 
$myquery .= "FROM tableA INNER JOIN tableB ON tableA.id = tableB.idTableA "; 
$myquery .= "WHERE tableA.time_start >='".$dateStart."' AND tableA.time_end <='".$dateEnd."'"; 

суммы Val (1-4) является правильной, но SUM от общего нет.

+0

Добавляйте только скобки: $ myquery. = "SUM (SUM (tableB.val1) + SUM (tableB.val2) + SUM (tableB.val3) + SUM (tableB.val4)) AS myValTotal"; –

+0

прошу пояснить, как суммируется сумма, тогда только это можно сделать, также сумма значений – mugdha

+0

@KrishnaGupta Я пробовал, но ничего не менял – Whiteboard

ответ

0

Совокупные ваши данные, прежде чем присоединиться, поэтому вы не ошибочно считаете значения многократными.

select sum(a.total) as mytotal, sum(b.sumval) as myvaltotal 
from tablea a 
left join 
(
    select idtablea, sum(val1+val2+val3+val4) as sumval 
    from tableb 
    group by idtablea 
) b on b.idtablea = a.id 
where a.time_start >= @start and a.time_end <= @end; 

То же самое с подзапросом в предложении SELECT. Это проще и обходит проблему, описанную Хуаном Карлосом Оропезой в комментариях ниже.

select 
    sum(total) as mytotal, 
    sum((
    select sum(val1+val2+val3+val4) 
    from tableb 
    where idtablea = tablea.id 
)) as sumvaltotal 
from tablea 
where time_start >= @start and time_end <= @end; 
+0

Даже когда эта работа и очень проста, вам нужно быть осторожным с performace, если таблицы большие, потому что во втором подзапросе нет фильтра, а join не будет использовать какой-либо индекс. –

+0

@Juan Карлос Оропеза: Я не вижу причин для этого не работать. Тем не менее, вы правы в том, что запрос написан таким образом, что фильтр применяется только после агрегирования всех записей в таблице. И это может привести к много ненужной работе, если у tableB было много записей за пределами данной области. Но обычно хорошая СУБД обрабатывает это внутренне и применяет фильтр (критерии соединения), как только они могут, чтобы не создавать ненужные служебные данные. Можно убедиться, добавив 'where idtablea in (select id from tablea where time_start ...)', но, как уже упоминалось, хорошая СУБД делает это внутренне. –

+0

@Juan Карлос Оропеза: Спасибо за ваши замечания в любом случае. Я добавил альтернативу моему ответу, который вообще обходит большой промежуточный результат. –

0

Вы должны проверить, какой диапазон перекрытия данных вы хотите, если частичный или общий.

Determine Whether Two Date Ranges Overlap

Кроме того, лучший способ проверить это скопировать запрос непосредственно на БД первого.

Проверьте диапазон данных в WHERE

SET @dateStart= '2015-12-01 00:00:00'; 
SET @dateEnd = '2015-12-30 23:59:59'; 

SELECT myTotal, myValTotal 
FROM 
    (
     SELECT SUM(tableA.total) AS myTotal 
     FROM tableA 
     WHERE tableA.time_start >= @dateStart 
     AND tableA.time_end <= @dateEnd ; 
    ) T1 
CROSS JOIN 
    (
     SELECT SUM(tableB.val1 + tableB.val2 + tableB.val3 + tableB.val4) AS myValTotal 
     FROM tableA 
     INNER JOIN tableB 
       ON tableA.id = tableB.idTableA 
     WHERE tableA.time_start >= @dateStart 
      AND tableA.time_end <= @dateEnd 
    ) T2; 
+0

не проблема с датой .. проверьте комментарий @HoneyBadger, спасибо – Whiteboard

+0

Хорошо, я обновляю свой ответ. Я использую ваш диапазон 'WHERE', но я по-прежнему верю, что вы должны проверить мою ссылку на определенные интервалы перекрытия –

0

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

select * from 
(
SELECT SUM(tableA.total) AS myTotal 
FROM tableA 
WHERE tableA.time_start <= @dateEnd 
    AND tableA.time_end >= @dateStart 
) x join (
SELECT SUM(tableB.val1) + SUM(tableB.val2) + 
     SUM(tableB.val3) + SUM(tableB.val4) AS myValTotal 
FROM tableB join tableA ON tableA.id = tableB.idTableA 
WHERE tableA.time_start <= @dateEnd 
    AND tableA.time_end >= @dateStart 
) y; 
0

В качестве отправной точки, это, кажется, легче читать ...

$myquery = 
" 
SELECT SUM(a.total) myTotal 
     , SUM(b.val1 + b.val2 + b.val3 + b.val4) myValTotal 
    FROM tableA a 
    JOIN tableB b 
    ON b.idTableA = a.id 
    WHERE a.time_start >='$dateStart' 
    AND a.time_end <='$dateEnd' 
"; 
+0

, которые выглядят хорошо, но не отвечают на вопрос –

0
SELECT 
SUM(tableB.val1) + SUM(tableB.val2) + SUM(tableB.val3) + SUM(tableB.val4) AS myValTotal, 
(SELECT SUM(total) from tableA where tableA.time_start >='2015-12-01 00:00:00' AND tableA.time_end <= '2015-12-30 23:59:59') as myTotal 
FROM tableA INNER JOIN tableB ON tableA.id = tableB.idTableA 
WHERE tableA.time_start >='2015-12-01 00:00:00' AND tableA.time_end <= '2015-12-30 23:59:59' 
0

Вы можете объявить переменную целого типа и сохранять значения сумм и снова sumup сохраненные значения, чтобы получить значение общего

  declare @val1 int 
      declare @val2 int 
      declare @val3 int 
      declare @val4 int 
      declare @newval int 

      select @val1= SUM(isnull(val1,0)) , @val2 = 
      sum(isnull(val2,0)), @val3=sum(isnull(val3,0)),@val4 = 
      sum(isnull(val2,0)) from TableB 

      select @newval = @val1 [email protected][email protected][email protected] 

@newval будет включать в себя сумму знач1 к val4

Смежные вопросы