汇总多列 - 意外结果

时间:2014-12-23 19:25:03

标签: mysql join

为什么

这会产生不正确的结果吗?

SELECT
    people.name,
    SUM(allorders.TOTAL),
    SUM(allorders.DISCOUNT),
    SUM(allorders.SERVICECHARGE),
    SUM(payments.AMOUNT)
FROM
    people
INNER JOIN
    allorders ON allorders.CUSTOMER = people.ID
INNER JOIN
    payments ON payments.CUSTOMER = people.ID
WHERE
    people.ID = 7 AND allorders.VOIDED = 0 AND payments.VOIDED = 0

给予:(名称),1644000,110000,50000,1485000

如果我在不同的查询中一次执行两个表(INNER JOIN people on allorders.CUSTOMER = people.ID),我会得到正确的结果。我甚至都不知道我得到的数字来自哪里。像:

SELECT
    people.name,
    SUM(allorders.TOTAL),
    SUM(allorders.DISCOUNT),
    SUM(allorders.SERVICECHARGE)
FROM
    people
INNER JOIN
    allorders ON allorders.CUSTOMER = people.ID
WHERE people.ID = 7 AND allorders.VOIDED = 0

给予:(名称),822000,550000,25000

SELECT
    people.name,
    SUM(payments.AMOUNT)
FROM
    people
INNER JOIN payments ON payments.CUSTOMER = people.ID
WHERE people.ID = 7 AND payments.VOIDED = 0

给:(名称),297000

看起来它翻了一番,但我不知道为什么。

奇怪的是我有一个类似的查询,正确地做这个总和。我会发布它,但它有点复杂。这是:

SELECT
    t1.IDENTIFIER,
    ifnull(t1.NAME,""),
    t1.PRICE,
    t1.GUESTS,
    t1.STATUS,
    ifnull(t1.NOTE,""),
    t1.LINK,
    ifnull(t1.EDITOR,""),
    concat(t2.FIRSTNAME,"",t2.LASTNAME),
    t2.ID,
    t3.ID,
    ifnull(t1.EMAIL,""),
    ifnull(t3.PHONE,""),
    ifnull(SUM(p1.AMOUNT),0),
    ifnull(SUM(o1.DISCOUNT),0),
    ifnull(SUM(o1.TOTAL),0),
    ifnull(SUM(o1.SERVICECHARGE),0)
FROM
    tables t1
INNER JOIN
    people t2 ON t1.SELLER = t2.ID
INNER JOIN
    people t3 ON t1.CUSTOMER = t3.ID
INNER JOIN
    orderpaymentinfo ON orderpaymentinfo.TABLEID = t1.IDENTIFIER
INNER JOIN
    payments p1 ON orderpaymentinfo.PAYMENTID = p1.PAYMENTID
INNER JOIN
     allorders o1 ON o1.ORDERID = orderpaymentinfo.ORDERID
WHERE
    p1.VOIDED = 0 AND o1.VOIDED = 0 AND t1.DATE = "2014-12-20"
GROUP BY t1.IDENTIFIER

后一个语句执行相同的连接,只是它使用了一个额外的帮助表。对不起它的格式有点差(我的格式化程序不是很好),但是如果有人能告诉我这两个语句中的逻辑与另一个语句完全错误之间的区别,我会非常高兴。

回答:

结果1:

Name - 5

结果2:

Name - 2

结果3:

Name - 10

结果4在phpMyAdmin中被截断 - 我在哪里可以轻松搞定?

这三个表的表结构如下:

SHOW在途中创造。

1 个答案:

答案 0 :(得分:1)

好的,所以我很确定你的连接条件基本上会将你的结果集爆炸成笛卡尔积。以下是我认为您应该尝试的内容

首先,运行以下命令并共享输出:

SELECT p.name,COUNT(*) 
FROM people  as p
INNER JOIN allorders  AS a
ON a.CUSTOMER = p.ID 
WHERE p.ID = 7 AND a.VOIDED = 0
GROUP BY p.name

然后运行

SELECT p.name,COUNT(*) 
FROM people  AS p
INNER JOIN payments AS pay
ON pay.CUSTOMER = p.ID 
WHERE p.ID = 7 AND pay.VOIDED = 0 
GROUP BY p.name

然后运行

 SELECT
        p.name,
        COUNT(*) 
   FROM
        people as p
    INNER JOIN
        allorders as a ON a.CUSTOMER = p.ID
    INNER JOIN
        payments as pay ON pay.CUSTOMER = p.ID
    WHERE
        p.ID = 7 AND a.VOIDED = 0 AND pay.VOIDED = 0
   GROUP BY p.name

上次运行以下

SHOW CREATE TABLE people;
SHOW CREATE TABLE payments;
SHOW CREATE TABLE allorders;

问题是您无法正确理解数据。您需要向我们提供有关数据和关系的更多信息,我在此处描述的输出应该有所帮助。我的不是答案。但是如果你运行这些查询并粘贴它们的输出,你应该能够从我或其他人那里得到答案。

根据上述讨论和编辑,请尝试:

SELECT
    p.name,
    SUM(o.TOTAL),
    SUM(o.DISCOUNT),
    SUM(o.SERVICECHARGE),
    MAX(pay.amt) 
FROM
    people as p
INNER JOIN
    allorders AS o ON o.CUSTOMER = p.ID
INNER JOIN (SELECT customer, 
            SUM(amount) as amt 
            FROM payments 
            WHERE voided = 0 AND customer = 7 
            GROUP BY customer) AS pay
     ON pay.customer = p.id
WHERE
    p.ID = 7 AND o.VOIDED = 0 
GROUP BY p.name

您也可以在SELECT语句中执行子查询,但这非常令人讨厌的imo。你也可以做min(pay.amt)或avg甚至只是完全离开聚合。以上应该有效...即使有更清洁的方法。我正在提供这个答案,所以你可以推断出为什么会得到意想不到的结果......实际上优化你的查询是一个不同的问题,你可以在以后找到它,一旦你有机会看到这个