2012-06-07 27 views
3

我正在寻找关于我正在为我的公司工作的项目的最有效表结构/ SQL代码的建议。我不是专业开发人员,所以更简单的解决方案是可取的。查询季度支出数据的改进表结构

项目要求:

我想创建一个显示总支出由供应商类别由财政季度,每个类别是可以点击的扩大来获得供应商级别x业务单元链接的HTML表级花费。

我已经有这个运行。我建立在PHP和MySQL。但是,在某些情况下,我运行的查询扩展表的运行速度非常慢。我希望彻底改革我的表格结构,并且要求整个过程更加高效和灵活。

总结,我有

数据我每季度获得的原始数据从各个业务单元由供应商支出。我还有一个解码器环,将供应商名称与供应商类别相匹配(例如,星巴克 - >餐厅)。

我的当前进程 我卷起季度数据到一个有以下的列spendfile称为表:

  • VENDORNAME
  • standard_vendor_name(校正拼错在供应商名称等)
  • vendor_category
  • 季度
  • 花费

当我从一个用户(首次)的请求,以查看HTML表类别下侧,按季度在单独的列花我创建一个名为treetable中有以下的列临时表:

  • rowlabel(类别/供应商的名字出现升降台的一侧)
  • spendQ1(与供应商的支出单独列在每季度)
  • spendQ2
  • spendQ3
  • spendQ4
  • 花...

注意的是,为了得到这个表,我需要选择所有的唯一的供应商类别,然后总和季度每个季度的花费和最后加入每个季度的季度总支出到类别列表(所以我正在做5-6个连接,每个时间段1个)。

然后我渲染为HTML表(非常简单)

当一个类别的用户点击来获得更多的细节,我经历了类似的过程:流汗厂商的唯一列表,总结支出(此时为所有供应商跨特定类别),并将所有时间段作为单独的列加​​入。

的最后一步是工会新的向下钻取数据到treetable中表中的正确位置(该类别下的所有供应商都属于)。

有没有人有更好的方法来做到这一点的任何想法?我正在努力做什么是有意义的?

感谢

+0

我很乐意帮助你,但我需要更多信息。你可以把你实际使用的查询来获取信息吗? – paquettg

+0

+1是一个很好的问题,供您的供应商拼写纠正和“解码器环” –

回答

0

很难提供具体的建议 - 如可能出现的SQL使用 - 不知道更多关于你的架构。不过,我会试试。以下是一些一般性建议。

  1. 尝试量化“非常缓慢”,这样您就可以知道在改进时是否改进了事物。还要量化您应对的数据量。
  2. 只使用临时表,如果你确定你需要它们。数据库管理系统中可能发生的最昂贵的(===慢)事件之一是将数据写入表格。如果你不需要临时表,不要使用它们。
  3. 如果你可以做到这一点,创建一个单一的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。假设您2011年第一季度至2012年第二季度使用20111,201212,20114,2012,2012等数字格式。

假设你想在你的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,1LIMIT 3,1LIMIT 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 

我会让你把子查询插入到这个大纲中。

您可能已经使用过类似的东西来生成临时表。但是如果你做对了,你可以简单地使用这个大的查询来生成你的报告。除非你的信息表有排列的行数,否则如果你正确地为你的表建立索引,它将会相当快地运行。

如果你拥有行数超越,你可能会为一家大公司工作,这个大公司可以用更快的磁盘和多个千兆字节的RAM来为更大的mySQL服务器发展。这也会加快速度,特别是一旦你编制索引。