2011-06-14 169 views
1

我正在尝试执行相当复杂的SQL查询来生成报表。这是库存和会计系统使用的数据库。复杂SQL查询帮助

基本上我需要制成具有以下列的报告

  • 月/年(组结果按月/年)
  • 经销商(为了结果由经销商与月/年组)
  • 总销售额 - 销售 - 硬件
  • 总销售额 - 销售 - 耗材

下表需要在报告中使用:

  • 发票
  • 经销商
  • 工作
  • JobStockItem
  • 股票

本质上查询需要作为开始:
1 。从发票中选择所有发票
2.获取经销商不适用我从Reseller.Name(使用Invoice.CustomerID加入Reseller.ID)
3.从作业表中获取关联的作业ID(使用Invoice.ID加入Job.InvoiceID)
4.从发票的每个组件JobStockItems(在Job.ID上加入JobStockItem.JobID)
5.从股票中获取股票项目(在Stock.ID上加入JobStockItems.StockId),并查看该类别(Stock.Category1)是硬件还是耗材
6.如果库存产品的硬件或消耗品,使用在JobStockItem(JobStockItem.PriceExTax)的销售价格,并将其添加对总的经销商购买

月份和年份都来自于一个月INVOIC e日期(Invoice.InvoiceDate)。

现在我可以通过执行一系列查询和处理自己来完成这个结果,每一步都可以执行上述步骤,但最终会变得很慢,而且我确定必须有一个查询那可以把所有这些要求都包装起来并且在一个中完成呢?

我还没有试图做这个查询,但说实话,我不知道从哪里开始 - 这比我过去做的任何事情都要复杂得多。

我只是使用Management Studio,没有使用Reporting Services,Crystal Reports或任何东西。我的目标是在输出时将输出转储为HTML。

感谢提前堆。

+0

我没有看到你从得到的月/年的信息 - 你似乎并不能够加入任何“销售”表之类的东西.. .. – 2011-06-14 04:41:37

+0

您使用什么工具生成报告? Crystal Reports,Microsoft Access,SQL Reporting ...等 – RThomas 2011-06-14 04:42:10

+0

到目前为止,您的尝试是什么?你试过去了吗? – Bohemian 2011-06-14 04:42:47

回答

4

它认为如果你离开加入JobStockItems表两次(一次为硬件,一次为消费品),你可以管理所有在一个查询。最终的查询将看起来像这样(没有我的编辑了,现在,这样的道歉任何错别字)

SELECT DATEPART(m, Invoice.InvoiceDate) month, 
     DATEPART(yy, Invoice.InvoiceDate) year, 
     Reseller.Name, 
     SUM(jobstockitems_hardware.Price) sales_hardware, 
     SUM(jobstockitems_consumables.Price) sales_consumables, 
FROM Invoice 
INNER JOIN Reseller 
ON Invoice.CustomerID = Reseller.ID 
INNER JOIN Job 
ON Invoice.ID = Job.InvoiceID 
LEFT JOIN (SELECT JobID, SUM(PriceExTax) Price 
      FROM JobStockItems 
      INNER JOIN Stock 
      ON JobStockItems.StockID = Stock.StockID 
      AND Stock.Category1 = 'Hardware' 
      GROUP BY JobID) jobstockitems_hardware 
ON Job.ID = jobstockitems_hardware.JobID 
LEFT JOIN (SELECT JobID, SUM(PriceExTax) Price 
      FROM JobStockItems 
      INNER JOIN Stock 
      ON JobStockItems.StockID = Stock.StockID 
      AND Stock.Category1 = 'Consumables' 
      GROUP BY JobID) jobstockitems_consumables 
ON Job.ID = jobstockitems_consumables.JobID 
GROUP BY DATEPART(m, Invoice.Date), 
     DATEPART(yy, Invoice.Date), 
     Reseller.Name 
ORDER BY DATEPART(yy, Invoice.Date) ASC, 
     DATEPART(m, Invoice.Date) ASC, 
     Reseller.Name ASC 

我假设零售商要返回以及一列称为名称,随时将其改为ID或其他任何您希望返回的内容。

编辑:固定的查询来删除重复

+0

您需要在子查询中总结硬件和耗材表(或与条件和的和 - SUM(CASE WHERE Category1 =?...)),否则结果将关闭('PriceExTax'将会是如果经销商有多个'stock_consumables'行,那么这两个类别都会重复。 – 2011-06-14 04:55:50

+0

你完全正确。我编辑了查询来反映这一点。 – dpmattingly 2011-06-14 05:05:37

+0

哇,荣誉 - 出色地工作。对不起,我的迟到的回复,一直没有透露。干杯@dp ... – Sam 2011-06-15 08:22:13

0

晴要枢结果。所以,你可以简单地一起加入您的数据,让PIVOT做类别的选择和总结:

select * 
from (
     select Year = datepart(year, i.InvoiceDate), 
       Month = datepart(month, i.InvoiceDate), 
       ResellerName = r.name, 
       StockCategory = s.Category1, 
       jsi.PriceExTax 
     from Invoice i 
     inner join Reseller r 
      on r.ID = i.CustomerID 
     inner join Job j 
      on j.InvoiceID = i.ID 
     inner join JobStockItem jsi 
      on jsi.JobID = j.ID 
     inner join Stock s 
      on s.ID = jsi.StockID 
     ) d 
pivot (sum(PriceExTax) for StockCategory in (Hardware, Consumables)) p 
order by Year, Month, ResellerName; 

到底你需要在内部查询某些情况下(例如在i.InvoiceDate之间... )。 您可能需要将PriceExTax与JobStockItem中的数量相乘......

0

DPMattingley已经生成了一个很好的查询,但有一个限制 - 如果时间段没有结果,它将不会显示任何行。在这里的具体例子中,这可能不太可能发生,但是在发生这种情况时,发现报告隐藏了零结果月份令人讨厌!

我的标准解决方案涉及从numbers table的月份,这迫使所有时间段出现。使用DPMattingley的查询为出发点 -

select 
    mths.month, 
    mths.year, 
    d.Name, 
    d.sales_hardware, 
    d.sales_consumables 
from 
    /*All the in-range months on which to report*/ 
    (select 
     datepart(m,dateadd(m,number,minDate)) month, 
     datepart(yy,dateadd(m,number,minDate)) year 
    from 
     numbers n 
      inner join (select min(invoice.invoicedate) as minDate from invoice) m 
       on n.number between 0 and datediff(m,minDate,getdate())) mths 

     left join 
      /*Data for each month*/ 
      (SELECT DATEPART(m, Invoice.InvoiceDate) month, 
        DATEPART(yy, Invoice.InvoiceDate) year, 
        Reseller.Name, 
        SUM(jobstockitems_hardware.Price) sales_hardware, 
        SUM(jobstockitems_consumables.Price) sales_consumables 
      FROM 
       Invoice 
        INNER JOIN Reseller 
         ON Invoice.CustomerID = Reseller.ID 
        INNER JOIN Job 
         ON Invoice.ID = Job.InvoiceID 
        LEFT JOIN (SELECT JobID, SUM(PriceExTax) Price 
           FROM JobStockItems 
           INNER JOIN Stock 
           ON JobStockItems.StockID = Stock.StockID 
           AND Stock.Category1 = 'Hardware' 
           GROUP BY JobID) jobstockitems_hardware 
         ON Job.ID = jobstockitems_hardware.JobID 
        LEFT JOIN (SELECT JobID, SUM(PriceExTax) Price 
           FROM JobStockItems 
           INNER JOIN Stock 
           ON JobStockItems.StockID = Stock.StockID 
           AND Stock.Category1 = 'Consumables' 
           GROUP BY JobID) jobstockitems_consumables 
         ON Job.ID = jobstockitems_consumables.JobID 
      GROUP BY DATEPART(m, Invoice.Date), 
         DATEPART(yy, Invoice.Date), 
         Reseller.Name) d 
       on mths.month=d.month 
       and mths.year=d.year 

ORDER BY mths.month ASC, 
      mths.year ASC, 
      Reseller.Name ASC