简体   繁体   English

Mysql:JOIN 2表中,SUM之一不正确

[英]Mysql : JOIN 2 table , one of the SUM is not correct

This is the structure of the two tables 这是两个表的结构

Table A 表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              

Table B 表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

The goal is the following : given a time_start and a time_end date , display the SUM of the totals (table A) and the SUM of the val1,val2,val3,val4 目标如下:给定一个time_start和一个time_end date,显示总计的总和(表A)和val1,val2,val3,val4的总和

Example : 范例

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

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

Result expected : sum of total = 500 , sum of val(1-4) = 120 预期结果 :总计= 500,val(1-4)等于120

I have tried so : 我已经尝试过了:

$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."'";

The SUM of the val(1-4) is correct , but the SUM of total not. val(1-4)的SUM正确,但合计的SUM不正确。

You have to check what kind of data range overlaps you want, if partial or total. 您必须检查想要重叠的数据范围是部分还是全部。

Determine Whether Two Date Ranges Overlap 确定两个日期范围是否重叠

Also the best way to test it is copy the query direct on the db first. 最好的测试方法是首先直接在数据库上复制查询。

Check the data range in the WHERE 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;

You shouldn't aggregate on multiplication of rows . 您不应该在行的乘法上进行汇总。 Rather aggregate two tables independently and then join them, something like: 而是独立地聚合两个表,然后将它们联接起来,例如:

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;

As a starting point, this seems easier to read... 作为起点,这似乎更容易阅读...

$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'
 ";
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'

Aggregate your data before you join, so you don't mistakenly consider values multifold. 在加入数据之前先汇总数据,这样您就不会误认为值是多重的。

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;

Here is the same with a subquery in the SELECT clause. 这与SELECT子句中的子查询相同。 It's simpler and circumvents the issue described by Juan Carlos Oropeza in below comments. 它更简单,可以绕开Juan Carlos Oropeza在以下评论中描述的问题。

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;

You can declare variable of int type and store the sum values , and again sumup the stored values to get value total 您可以声明int类型的变量并存储总和值,然后再次对存储的值求和以获得总值

          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 +@val2+@val3+@val4

@newval will include the sum of val1 to val4 @newval将包括val1与val4之和

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM