复杂的SQL查询帮助

时间:2011-06-14 04:31:32

标签: sql sql-server tsql

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

基本上我需要使用以下列生成报告

  • 月/年(按月/年分组的结果)
  • 经销商(经销商在月/年组中订购结果)
  • 总销售额 - 销售额 - 硬件
  • 总销售额 - 销售额 - 耗材

报告中需要使用以下表格:

  • 发票
  • 经销商
  • 工作
  • JobStockItem
  • 库存

基本上,查询需要以下列方式开始:
1.从发票
中选择所有发票 2.从Reseller.Name获取经销商名称(使用Invoice.CustomerID加入Reseller.ID)
3.从Job表中获取关联的作业ID(使用Invoice.ID加入Job.InvoiceID)
4.从JobStockItems获取发票的每个组成部分(在Job.ID上加入JobStockItem.JobID)
5.从Stock中获取作业中的库存项目(在Stock.ID上加入JobStockItems.StockId)并查看类别(Stock.Category1)是硬件还是耗材
6.如果库存项目是硬件或消耗品,请使用JobStockItem(JobStockItem.PriceExTax)中的销售价格并将其添加到经销商购买月份的总额中

月份和年份来自发票日期(Invoice.InvoiceDate)。

现在我可以通过执行一堆查询和处理自己来生成这个结果,每个都用于上述步骤,但它最终会变慢,我确信那里必须有一个查询可以将所有这些要求包起来并在一个中完成吗?

我还没有尝试过查询,说实话,我不知道从哪里开始 - 它比我过去所做的任何事都复杂得多。

我只使用Management Studio,而不是使用Reporting Services,Crystal Reports或其他任何东西。我的目标是在工作时将输出转储为HTML。

提前谢谢你们。

3 个答案:

答案 0 :(得分: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

我假设零售商有一个名为Name的列,您也想要返回,可以随意将其更改为ID或其他您想要返回的内容。

编辑:修复查询以删除重复项

答案 1 :(得分: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中的金额相乘......

答案 2 :(得分: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
相关问题