2013-10-29 33 views
0

我有一个实现SQL的Access项目,并且我一直致力于优化对帐过程。此过程使用将所有表链接在一起的凭证系统。 每个表格中的每条记录都有一个与金额相关的特定凭证ID。 代金券本身是唯一的,可以包含多个代金券号码,可以在下面看到。如何优化这个SQL查询在相关表中的总和?

Table: Rec_Vouchers 
v_id  v_num  voucher 
1   12341234 12341234 
2   10101010 10101010;22222222 
2   22222222 10101010;22222222 
... 

我有8个通过这些凭证ID链接的其他表。我试图将所有表格连接在一起,以显示具有该特定凭证ID的每张表格的区分凭证ID和凭证以及所有相应金额的总和。以下是查询和结果示例。我已经为此工作了一段时间了,现在开始让我头疼了。这个查询可以工作,但需要很长时间才能执行。

此外,在某些时候,我需要将所有这些值匹配在一起,以确定凭证是“匹配”,“不匹配”还是“匹配带有差异”。到目前为止,我只尝试在下面的代码中创建一个函数,该函数将返回字符串值“M”,“NM”或“MwD”以显示在每个凭证的列中。再次,这是有效的,但需要很长时间。我也试着让VBA用查询的返回记录集做这个肮脏的工作,这也需要很多时间,但不会像在我的sql查询中创建函数那样长。这是下一步,所以如果你可以帮助所有这些会很好,但我真的只需要优化我提供的查询。

我知道这是一个很好的包装你的头,所以让我知道你是否需要任何更多的信息。任何帮助,将不胜感激。谢谢!

select a.v_id, a.voucher, 
(Select sum(b.amount) from rec_month_4349_test b where b.voucher = a.v_id) as GL, 
(Select sum(c.payments) from rec_daily_balancing_test c where c.voucher = a.v_id) as DB, 
(Select count(x.v_num) from rec_vouchers x where a.v_id = x.v_id and x.v_num not like 'ONL%') as GLcount, 
(select count(c.batch_num) from rec_daily_balancing_test c where a.v_id = c.voucher) as DBcount, 
(select sum(d.amount) from rec_ed_test d where a.v_id = d.voucher) as ED, 
(select sum(e.batchtotal) from rec_eft_batches_new_test e where a.v_id = e.voucher) as EFT, 
(select sum(f.batchtotal) from rec_check_batch_test f where a.v_id = f.voucher) as CHK, 
(select sum(g.idxtotal) from rec_lockbox_test g where a.v_id = g.voucher) as LBX, 
(select sum(h.amount) from rec_lcdl_test h where a.v_id = h.voucher) as LCDL, 
((select sum(i.payment_amount) from rec_electronic_files_test i where a.v_id = i.voucher) + (select sum(j.amount) from rec_electronic_edits_test j where a.v_id = j.voucher)) as Elec 
from rec_vouchers a 
group by a.v_id, a.voucher 

Sample Results: 
v_id  GL   DB   GLcount DBcount  ED  EFT  CHK  LBX  LCDL  Elec 
6131  19204.00 19204.00 1   1   NULL NULL NULL NULL NULL  NULL 
6132  125330.00 14932.00 6   6   NULL NULL NULL NULL NULL  14932.00 
6133  18245.00 NULL  2   0   NULL NULL NULL NULL NULL  NULL 
6175  98.93  98.93  1   1   NULL 98.93 NULL NULL NULL  NULL 
+0

为什么这个标签为sql-server,如果一切都在MS Access? –

+0

您要求优化访问还是SQL Server? –

+0

一切都不在Access中。所有rec_ *表都是数据库中的SQL表。所有Access都会调用上面创建的视图将结果导出到Excel电子表格中。 –

回答

0

我们很容易地说,“传统”的方式来写这个查询是由表移动到使用join谓词from条款。但是,这可能会引入不必要的笛卡尔产品。你的方法其实很好,另一种方法是将left joins作为聚合子查询。

表现的杀手可能是由于骑单车通过表找到匹配。您可以通过在每个查询的where子句中使用字段上的索引来显着提高性能。例如,对于前两个表,您应该有一个索引rec_month_4349_test(voucher)rec_daily_balancing_test(voucher)

在SQL Server中,您还可以通过在索引中包含用于求和的变量来进一步优化此查询。以下索引会更好:rec_month_4349_test(voucher, amount)rec_daily_balancing_test(voucher, payments)(或者您可以将它们包含在索引中而不被搜索,这是更先进的)。

此优化适用于大多数数据库(索引扫描而不是索引查找)。我不知道它是否适用于MS Access(我尽可能避免的软件产品)。

请记住,您需要为所有表格执行此操作。

0

不知道这是否是最佳解决方案,但我为每个表单创建了单独的视图来选择优惠券和每个特定优惠券的金额总和。每个视图看similair以下几点:

rec_sum4349

SELECT voucher, sum(amount) AS GL 
FROM rec_month_4349_test 
GROUP BY voucher 

然后我有一个观点,即结合一起使用完全独立的视图中加入类似如下:

rec_vouch_test

SELECT a.voucher, a.GL, b.DB 
FROM rec_sum4349 a 
FULL JOIN rec_sumDB b 
ON a.voucher = b.voucher 
WHERE a.voucher IS NOT NULL AND a.voucher <> '' 
ORDER BY a.voucher 

当我看到这个工作原理很好,我为剩下的表格创建了我需要总结的观点并将它们添加到上述观点中。结果正是我所期待的,运行时间从几乎2分钟缩短到几秒钟!感谢所有的帮助。现在开始配合一切!

0

相关的子查询是我最喜欢的选择。

我会建议编写子查询并连接每个表,以便每个表都可以利用它们上的索引。

在每个表上创建以下索引并查看下面的查询。

rec_vouchers

聚集索引(v_id,凭单)

筛选非聚集索引(v_num)WHERE v_num NOT LIKE 'ONL%'

rec_month_4349_test

非集群索引(优惠券)包含(金额)

rec_daily_balancing_test

非聚集索引(券)包含(付款)

rec_ed_test

非聚集索引(券)包含(量)

rec_eft_batches_new_test

非聚集索引(vouche R)包括(batchtotal)

rec_check_batch_test

非聚集索引(券)包括(batchtotal)

rec_lockbox_test

非聚集索引(券)包括(idxtotal)

rec_lcdl_test

非聚集索引(券)包含(量)

rec_electronic_files_test

非聚集索引(券)包含(支付金额)

rec_electronic_edits_test

非聚集索引(凭单)包括(金额)

SELECT a.v_id,a.voucher 
      ,t1.GL ,t2.DB ,t3.GLcount 
      ,t4.DBcount ,t5.ED ,t6.EFT 
      ,t7.CHK ,t8.LBX ,t9.LCDL 
      ,(t10.Elec1+t11.Elec2) AS Elec 
    FROM 
    (SELECT t0.v_id ,t0.voucher 
     FROM rec_vouchers t0 
     GROUP BY t0.v_id ,t0.voucher 
    )a 
    JOIN 
    (SELECT SUM(b.amount) AS GL,b.voucher 
     FROM rec_month_4349_test b 
     Group By b.voucher 
    ) t1 
     ON a.v_id=t1.voucher 
    JOIN 
    (SELECT SUM(c.payments) AS DB,c.voucher 
     FROM rec_daily_balancing_test c 
     Group By c.voucher 
    ) t2 
     ON a.v_id=t2.voucher 
    JOIN 
    (SELECT COUNT(x.v_num) AS GLcount,x.v_id 
     FROM rec_vouchers x 
     WHERE x.v_num NOT LIKE 'ONL%' 
     Group BY x.v_id 
    ) t3 
     ON a.v_id=t3.v_id 
    JOIN 
    (SELECT COUNT(c.batch_num) AS DBcount,c.voucher 
     FROM rec_daily_balancing_test c 
     Group By c.voucher 
    ) t4 
     ON a.v_id=t4.voucher 
    JOIN 
    (SELECT SUM(d.amount) AS ED,d.voucher 
     FROM rec_ed_test d 
     Group By d.voucher 
    ) t5 
     ON a.v_id=t5.voucher 
    JOIN 
    (SELECT SUM(e.batchtotal) AS EFT,e.voucher 
     FROM rec_eft_batches_new_test e 
     Group By e.voucher 
    ) t6 
     ON a.v_id=t6.voucher 
    JOIN 
    (SELECT SUM(f.batchtotal) AS CHK,f.voucher 
     FROM rec_check_batch_test f 
     Group By f.voucher 
    ) t7 
     ON a.v_id=t7.voucher 
    JOIN 
    (SELECT SUM(g.idxtotal) AS LBX,g.voucher 
     FROM rec_lockbox_test g 
     Group By g.voucher 
    ) t8 
     ON a.v_id=t8.voucher 
    JOIN 
    (SELECT SUM(h.amount) AS LCDL,h.voucher 
     FROM rec_lcdl_test h 
     Group By h.voucher 
    ) t9 
     ON a.v_id=t9.voucher 
    JOIN 
    (SELECT SUM(i.payment_amount) AS Elec1,i.voucher 
     FROM rec_electronic_files_test i 
     GROUP BY i.voucher 
    ) t10 
     ON a.v_id=t10.voucher 
    JOIN 
    (SELECT SUM(j.amount) AS Elec2,j.voucher 
     FROM rec_electronic_edits_test j 
     GROUP BY j.voucher 
    ) t11 
     ON a.v_id=t11.voucher