2012-03-05 56 views
0

我有2个表格(针对这个问题)公司和发票。一个公司可以有多个发票,并且它们通过一个company_id自动递增相关联。我正在寻找每个有发票的公司的最新发票数据。
我不只想要最近的相关记录的日期,而是来自相关记录的各种数据。MySQL获取最近相关记录的数据

我尝试了几种不同的方法,但我现在的查询是可怕的......它让我痛苦的不得不诉诸于关系数据库中这样的事情。
这里的查询......

SELECT `companies`.`company_name`, `invoices_latest`.`data`, 
SUBSTRING_INDEX(SUBSTRING_INDEX(`invoices_latest`.`data`, '~', 1), '~', -1) AS `last_invoice_stamp`, 
SUBSTRING_INDEX(SUBSTRING_INDEX(`invoices_latest`.`data`, '~', 2), '~', -1) AS `last_invoice_id`, 
SUBSTRING_INDEX(SUBSTRING_INDEX(`invoices_latest`.`data`, '~', 3), '~', -1) AS `last_invoice_reference`, 
SUBSTRING_INDEX(SUBSTRING_INDEX(`invoices_latest`.`data`, '~', 4), '~', -1) AS `last_invoice_amount` 
FROM `companies` 
INNER JOIN 
(
SELECT `company_id`, MAX(CONCAT_WS('~', `invoice_stamp`, `invoice_id`, `reference`, CONCAT_WS(' ', `currency`, FORMAT(`amount`, 2)))) AS `data` 
FROM `invoices` 
GROUP BY `invoices`.`company_id` 
) AS `invoices_latest` ON `companies`.`company_id`=`invoices_latest`.`company_id` 
WHERE `invoices_latest`.`data` IS NOT NULL 
ORDER BY `companies`.`company_name`

连接Data派生表,然后父查询中分裂出来是可怕的,但它是我发现要达到什么我正在寻找的唯一途径。

我想这...

SELECT `companies`.`company_id`, `companies`.`company_name`, `invoices_latest`.`invoice_id`, FROM_UNIXTIME(`invoices_latest`.`invoice_stamp`) 
FROM `companies` 
LEFT JOIN (
SELECT `company_id`, `invoice_id`, `invoice_stamp` 
FROM `invoices` 
ORDER BY `invoice_stamp` DESC 
LIMIT 0, 1 
) AS `invoices_latest` ON `companies`.`company_id`=`invoices_latest`.`company_id` 
WHERE `invoices_latest`.`invoice_id` IS NOT NULL

但预期它不工作,只返回1行 - 因为我相信在派生表规定的实际适用于父查询。这是一个耻辱,你不能这样做,因为这将是一个易于阅读的解决方案。

有没有更好的选择,我上面已经进行了可怕的连接?

回答

0
select company,*, invoice.* 
from company, invoice 
where company.company_id = invoice.company_id 
and (invoice.company_id, invoice.date) in (
    select company_id, max(date) from invoices group by company_id 
); 
+0

这是一个很好的解决方案,但似乎需要一个年龄相比,我上面的可怕方法... 76秒vs 0.0142。我有关于invoices.company_id,invoices.invoice_id(主要),invoices.invoice_stamp,companies.company_id(主要)的索引。我认为这是WHERE ... IN子句中的子查询,它们似乎总是需要一段时间。感谢您的建议! – batfastad 2012-03-05 23:59:20

+0

将一个字段(latest_invoice_id)添加到公司表中,并通过发票表中的每个插入,更新或删除操作通过触发器对其进行维护。 – 2012-03-06 09:27:07

+0

/*这是我刚刚删除的一个愚蠢的想法。 */ – 2012-03-06 13:47:53

0

我的建议是接近它是这样的:

SELECT * FROM `invoice` WHERE `company_id`=ID ORDER BY `date` DESC LIMIT 25; 

,如果你没有在命令中指定的ID,您可以选择所有公司的ID,做同样的事情,每个几乎与一个类似的命令:

SELECT * FROM `invoice` WHERE `company_id` IN(SELECT `company_id` FROM `companies`) ORDER BY `date` DESC LIMIT 25; 
+0

如果没有LIMIT子句,则返回系统中的所有发票。大多数公司有超过1张发票,我只是想要为每家公司返回最近的发票(以及发票值和发票表中的其他各个字段)。此外,我确实需要构建查询“FROM companies”,因为我正在寻找其他连接添加到来自公司表的其他相关数据。干杯! – batfastad 2012-03-06 00:05:18