在具有6个连接表的选择查询期间检索错误的ID

时间:2016-07-15 08:10:40

标签: php mysql

这是我的表格:

cb_paymentscheduledetail

id | name                  | date_entered          | deleted | due_date   | amount | status
1  | #1 Payment For Inv# 1 | 2016-07-15 06:11:55   | 0       | 2016-07-08 | 147.25 | Unpaid
2  | #2 Payment For Inv# 1 | 2016-07-15 06:11:55   | 0       | 2016-07-15 | 147.25 | Unpaid
3  | #1 Payment For Inv# 3 | 2016-07-14 13:00:21   | 0       | 2016-07-18 | 4.58   | Unpaid
4  | #2 Payment For Inv# 3 | 2016-07-14 13:00:21   | 0       | 2016-07-21 | 4.58   | Unpaid
5  | #1 Payment For Inv# 2 | 2016-07-14 12:56:35   | 0       | 2016-07-22 | 50.00  | Unpaid
6  | #3 Payment For Inv# 1 | 2016-07-15 06:11:55   | 0       | 2016-07-22 | 147.25 | Unpaid

cb_paymentscheduleheader

id  |  installment_type
1   |  auto
2   |  auto
3   |  manual

cb_paymentscheduleheader_cb_paymentscheduledetail_c

id | cb_payment37a2eheader_ida | cb_paymente42dedetail_idb
1  | 1                         | 5
2  | 2                         | 6
3  | 2                         | 1
4  | 2                         | 2
5  | 3                         | 3
6  | 3                         | 4

aos_invoices

id | number | billing_account_id
1  | 1      | 1
2  | 2      | 2
3  | 3      | 3

帐户

id | phone_office | name
1  | 123          | a
2  | 123          | b
3  | 123          | c

email_addr_bean_rel

email_address_id | bean_id
1                | 1
2                | 2
3                | 3

EMAIL_ADDRESSES

id | email_address
1  | test@test.com
2  | test@test3.com
3  | test@test4.com

我的查询:

SELECT cb_paymentscheduledetail.id , cb_paymentscheduledetail.amount , cb_paymentscheduledetail.assigned_user_id 
    ,MIN(cb_paymentscheduledetail.due_date) as min_date, cb_paymentscheduledetail.name, 
    cb_paymentscheduledetail.amount, aos_invoices.number, aos_invoices.billing_account_id,
    accounts.id as account_id, accounts.phone_office as account_phone, accounts.name as account_name, 
    email_addr_bean_rel.email_address_id, email_addr_bean_rel.bean_id, email_addresses.email_address as account_email, 
    cb_paymentscheduleheader_cb_paymentscheduledetail_c.id as headerdetail_id, 
    cb_paymentscheduleheader_cb_paymentscheduledetail_c.cb_paymente42dedetail_idb, 
    cb_paymentscheduleheader_cb_paymentscheduledetail_c.cb_payment37a2eheader_ida, cb_paymentscheduleheader.id as header_id, 
    cb_paymentscheduleheader.installment_type  
    FROM cb_paymentscheduledetail  
    LEFT JOIN aos_invoices ON aos_invoices.number = SUBSTRING_INDEX(cb_paymentscheduledetail.name, ' ', -1) 
    INNER JOIN accounts ON aos_invoices.billing_account_id = accounts.id 
    INNER JOIN email_addr_bean_rel ON accounts.id = email_addr_bean_rel.bean_id 
    INNER JOIN email_addresses ON email_addresses.id = email_addr_bean_rel.email_address_id  
    INNER JOIN cb_paymentscheduleheader_cb_paymentscheduledetail_c ON cb_paymentscheduledetail.id = cb_paymentscheduleheader_cb_paymentscheduledetail_c.cb_paymente42dedetail_idb  
    INNER JOIN cb_paymentscheduleheader ON cb_paymentscheduleheader_cb_paymentscheduledetail_c.cb_payment37a2eheader_ida = cb_paymentscheduleheader.id    
    WHERE cb_paymentscheduledetail.deleted = 0 AND cb_paymentscheduledetail.status = 'Unpaid' AND (cb_paymentscheduledetail.due_date BETWEEN '2016-07-15' AND '2016-07-22') 
    GROUP BY cb_paymentscheduledetail.date_entered 
    ORDER BY cb_paymentscheduledetail.due_date ASC;

我的问题是,此查询的ID提取对于 147.25 的金额不正确,尽管它获取的min_date是正确的:

查询的min_date如下:

4.58 = 2016-07-18
50.00 = 2016-07-22
147.25 = 2016-07-15

ID应分别为:

4.58 = 3
50.00 = 5
147.25 = 2

但实际ID是:

4.58 = 3
50.00 = 5
147.25 = 6

正如你所看到的数量“147.25”它正在获得due_date 2016-07-22当它在MIN函数中得到了正确的2016-07-15时,它也得到正确的ID应该是2而不是6,有没有人能够帮助我,因为我不能再看到问题是什么了?既然它不应该从一开始就根据我的min_date检索到合适的ID吗?

选择2016-07-15的唯一时间是我将BETWEEN更改为:

cb_paymentscheduledetail.due_date = '2016-07-15'

但是我不知道这是什么,因为我需要在日期之间

1 个答案:

答案 0 :(得分:2)

  

当它从一开始就变得正确时,它不应该根据我的min_date检索相应的ID吗?

简短的回答是

对于SELECT子句中存在的与以下内容不匹配的所有表达式,MySQL返回一些看似随机的值:

  • 表达式也出现在GROUP BY子句中;
  • 表达式使用GROUP BY aggregate functions;
  • 表达式在功能上取决于GROUP BY子句中出现的列。

这是documented behaviour,因为GROUP BY的工作方式,它应该如何。

GROUP BY 从数据库中选择行。它使用数据库中的值生成记录。查询的SELECT子句中出现的每个表达式(也包含GROUP BY子句都是独立于其他表达式计算的。

稍微考虑一下。假设它应该按照您的意愿工作,如果将MIN()替换为另一个GROUP BY aggregate function,查询将返回什么值?以AVG()为例。最有可能的是,cb_paymentscheduledetail表中的任何行都没有列due_date AVG(due_date)返回的值INNER JOIN。还是COUNT()?它们甚至没有相同的类型。

查看类似问题上提供的this answer,了解编写查询的正确方法,该查询返回特定列中其组中具有最小/最大值的行。它可以通过o扩展到容纳六个表 - 使用从中选择行的表(表paymentscheduledetail中的表)。

如果您无法以这种方式处理它,您可以将查询拆分为两个较小的查询(您甚至可以在以后使用子查询合并它们):MIN(due_date)上的一个查询选择date_entered并按{分组{1}}和另一个查询,它使用第一个查询返回的值来选择所需的行。考虑到可以有多行due_date的最小值。