如果不了解有关您的架构的更多信息,很难提供具体的建议(例如可能使用的 SQL)。不过,我会努力的。以下是一些一般性建议。
- 尝试量化“非常缓慢”,这样您就可以知道您是否在改进时进行改进。还要量化您要处理的数据量。
- 仅在您绝对确定需要临时表时才使用它们。DBMS 中可能发生的最昂贵(=== 慢)的事情之一是将数据写入表。如果您不需要临时表,请不要使用它们。
- 如果可以,请创建一个 SQL 查询,为您希望从原始数据以 HTML 格式显示的表生成正确的列和行。然后,在命令行 mySQL 客户端中运行该查询并使用 EXPLAIN 命令让 mySQL 告诉您它正在尝试做什么。见这里:http ://dev.mysql.com/doc/refman/5.0/en/explain.html
以下是有关该查询如何工作的一些更具体的建议。假设您的输入表具有此架构。
vendorname
standard_vendor_name (corrects misspells in vendor name, etc.)
vendor_category (character string)
quarter (integer)
spend (floating point)
假设您想要一个包含这些列的表
vendor_category
vendor (standardized spelling)
spend_q1
spend_q2
spend_q3
spend_q4
很抱歉,我不明白您关于如何处理输出中的供应商名称和类别的问题。我假设您只是显示类别,然后显示每个供应商的名称,并按类别排序。
我也不明白你是如何quarter
在你的输入表中存储的。假设您在 1Q2011 - 2Q2012 使用数字格式,例如 20111、20112、20113、20114、20121、20122。
假设您想在 html 表格中显示任意四个连续的季度,只是为了笑。
所以,我们开始吧。
我们需要一个小子查询来根据您要显示的最近一个季度的 ID(您需要提供)生成您需要的四个季度 ID。
SELECT DISTINCT QUARTER
FROM INFO
WHERE QUARTER <= ~~~the most recent quarter~~~
ORDER BY QUARTER DESC
LIMIT 0,4
如果您总是从最近一个季度开始,您可以简单地忽略WHERE QUARTER <= ~~~the most recent quarter~~~
这个小子查询,它会获取您拥有的最新数据。
其次,我们需要将季度列表子查询构建为子查询,以生成最新季度的数据。
SELECT I.QUARTER, I.VENDOR_CATEGORY, I.STANDARD_VENDOR_NAME, SUM(I.SPEND) SPEND
FROM INFO I
JOIN (
SELECT DISTINCT QUARTER
FROM INFO
WHERE QUARTER <= ~~~the most recent quarter~~~
ORDER BY QUARTER DESC
LIMIT 0,1
) Q ON I.QUARTER=Q.QUARTER
GROUP BY I.QUARTER, I.VENDOR_CATEGORY, I.STANDARD_VENDOR_NAME
这是我们基本的季度查找构建块。此时很明显,您将需要您的 INFO 表在 QUARTER 和 VENDOR_CATEGORY 列上有索引。
您可能需要对这两者,甚至是 (QUARTER, VENDOR_CATEGORY, STANDARD_VENDOR_NAME) 的复合索引。但是让事情正常进行。然后查看 EXPLAIN 输出。然后尝试添加其他索引。在您继续之前,值得摆弄索引以优化此构建块查询。
我们还需要三个这样的小子查询,每个前一个季度一个。LIMIT 0,1
除了、LIMIT 1,1
、LIMIT 3,1
和之外,子查询与构建块相同LIMIT 4,1
。
我们还需要一个我们需要显示的所有 VENDOR_CATEGORY 和 STANDARD_VENDOR_NAME 组合的主列表。此查询会弹出在您正在考虑的任何季度中出现一次或多次的任何类别/供应商组合的结果。
SELECT DISTINCT I.VENDOR_CATEGORY, I.STANDARD_VENDOR_NAME
FROM INFO I
JOIN (
SELECT DISTINCT QUARTER
FROM INFO
WHERE QUARTER <= ~~~the most recent quarter~~~
ORDER BY QUARTER DESC
LIMIT 0,4
) Q ON I.QUARTER=Q.QUARTER
不要在这一项中进行 LEFT JOIN,否则您最终会得到所有类别/供应商项目,包括您在最近四个季度没有花钱的项目。
现在我们需要把它们放在一起。事情变得荒谬的冗长(SQL 不是很有趣吗?)。我们必须将所有这些构建块连接在一起。这是我们的大查询的大纲,并带有注释以显示构建块的去向。
SELECT A.VENDOR_CATEGORY, A.STANDARD_VENDOR_NAME, Q.SPEND, R.SPEND, S.SPEND, T.SPEND
FROM (
/* category combinations */
)A
LEFT JOIN (
/* most recent quarter spend */
)Q ON ( A.VENDOR_CATEGORY=Q.VENDOR_CATEGORY
AND A.STANDARD_VENDOR_NAME=Q.STANDARD_VENDOR_NAME)
LEFT JOIN (
/* second most recent quarter spend */
)R ON ( A.VENDOR_CATEGORY=R.VENDOR_CATEGORY
AND A.STANDARD_VENDOR_NAME=R.STANDARD_VENDOR_NAME)
LEFT JOIN (
/* third most recent quarter spend */
)S ON ( A.VENDOR_CATEGORY=S.VENDOR_CATEGORY
AND A.STANDARD_VENDOR_NAME=S.STANDARD_VENDOR_NAME)
LEFT JOIN (
/* fourth most recent quarter spend */
)T ON ( A.VENDOR_CATEGORY=T.VENDOR_CATEGORY
AND A.STANDARD_VENDOR_NAME=T.STANDARD_VENDOR_NAME)
ORDER BY A.VENDOR_CATEGORY, A.STANDARD_VENDOR_NAME
我将留给您将子查询插入此大纲。
您可能已经使用过类似的方法来生成临时表。但如果你做对了,你可以简单地使用这个大查询来生成你的报告。除非您的信息表有数以亿计的行,否则如果您正确索引表,它将运行得相当快。
如果您确实有数以亿计的行,那么您可能为一家大公司工作,该公司可以为具有快速磁盘和数 GB RAM 的更大的 mySQL 服务器而生。这也将加快速度,尤其是在您制定索引后。