我的数据库中有2个记录金额,我必须使用sum函数来显示总数,但它显示和总和两次
我在同一查询及其工作中尝试了其他总和函数,但是当我第二次使用时,它总和两次。
$sql = "SELECT
mm.idno as idno,
TRIM(UPPER(CONCAT(mm.fname, ' ', mm.mname, ' ', mm.lname))) as fullname,
TRIM(UPPER(mm.branchname)) as branchname,
TRIM(UPPER(mm.address)) as outlet_address,
SUM(dr.totalamt) as total_amount,
SUM(drr.totalamt) as return_amount
FROM 8_membermain mm
LEFT JOIN 8_directsalessummary dr ON mm.idno = dr.idno
LEFT JOIN 8_drreturnsummary drr ON dr.idno = drr.idno
WHERE mm.status > 0 AND dr.status = 1
AND dr.ispaid = 'Full Payment'
AND dr.trandate BETWEEN '".$date1."' AND '".$date2."'
AND drr.trandate BETWEEN '".$date1."' AND '".$date2."'";
SUM(dr.totalamt) as total_amount
工作正常。唯一的问题是SUM(drr.totalamt) as return_amount
从您对问题的描述中,听起来您的查询与两个Dr行和一排匹配。如果有一个以上的DRR行,DR总数也将是错误的。这是因为加入返回连接表的所有可能组合。例如,如果有两个DR行,我们将称为A和B,以及三个DRR行C,D和E,结果(由于使用sum,在将sum组合成一排之前(是:
A and C
A and D
A and E
B and C
B and D
B and E
总结DR列时,A和B的值分别遇到三次,导致三倍。当总结DRR列时,C,D和E的值分别遇到两次,导致加倍的总和。
正确的解决方法是加入DR和DRR的子征服,如Tim的答案中所示。但是有时候,如果涉及的表很少,每个分组中的记录很少,并且表具有主键或其他独特的列,则可以简单地将每个总和除以彼此的行数(或1如果没有行(:
SELECT
...
SUM(dr.totalamt)/GREATEST(1,COUNT(DISTINCT drr.primarykey)) as total_amount,
SUM(drr.totalamt)/GREATEST(1,COUNT(DISTINCT dr.primarykey)) as return_amount
您查询的其他几个评论:
似乎您打算在最后要有一个GROUP BY mm.idno
。没有这些,您的查询将返回与MM相关字段的数据,以符合您的Where标准的任意MM记录,并且如果您的查询实际上找到了多个MM Records,则上述技巧将无法正常工作。
您使用左连接,但是在Where子句中指定条件,如果找不到行,将是错误的;实际上,这使您的左连接是内在的连接。如果您想找到MM行,即使没有DR或DRR行,也需要将条件移入联接中,例如:
LEFT JOIN 8_directsalessummary dr ON mm.idno = dr.idno
AND dr.status = 1
AND dr.ispaid = 'Full Payment'
AND dr.trandate BETWEEN ...
另外,您正在使用Dr.Idno加入DRR;如果您想查找DRR记录,即使没有DR记录,也应该使用mm.idno:
LEFT JOIN 8_drreturnsummary drr ON mm.idno = drr.idno
AND drr.trandate BETWEEN ...
您的方法的问题是您加入了两次 first ,然后汇总。SUM(dr.totalamt)
之所以起作用,是因为它仅涉及第一个加入。但是SUM(drr.totalamt)
是不正确的,因为由于第二个联接而导致您过分倒数。要解决此问题,您应该在单独的子征服中执行聚合,然后加入这些子征服:
SELECT
mm.idno,
TRIM(UPPER(CONCAT(mm.fname, ' ', mm.mname, ' ', mm.lname))) AS fullname,
TRIM(UPPER(mm.branchname)) AS branchname,
TRIM(UPPER(mm.address)) AS outlet_address,
COALESCE(dr.totalamt, 0) AS total_amount,
COALESCE(drr.totalamt, 0) AS return_amount
FROM 8_membermain mm
LEFT JOIN
(
SELECT idno, SUM(totalamt) AS totalamt
FROM 8_directsalessummary
WHERE status = 1 AND ispaid = 'Full Payment' AND
trandate BETWEEN ? AND ?
GROUP BY idno
) dr
ON mm.idno = dr.idno
LEFT JOIN
(
SELECT idno, SUM(totalamt) AS totalamt
FROM 8_drreturnsummary
WHERE trandate BETWEEN ? and ?
GROUP BY idno
) drr
ON mm.idno = drr.idno
WHERE
mm.status > 0;
对于?
占位符,您需要绑定两个日期值$date1
和$date2
。但是,关于如何在PHP中使用准备好的陈述的另一个解释似乎太广泛了,查询逻辑的问题似乎是更大的问题。