繁体   English   中英

复杂 SQL 查询帮助

[英]Complex SQL Query Help

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

基本上我需要生成一个包含以下列的报告

  • 月/年(按月/年分组结果)
  • 转销商(月/年组中转销商的订单结果)
  • 总销售额 - 销售额 - 硬件
  • 总销售额 - 销售额 - 消耗品

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

  • 发票
  • 经销商
  • 工作
  • 工作库存项目
  • 库存

本质上,查询需要以以下方式开始:
1. Select 所有发票来自 Invoice
2. 从 Reseller.Name 获取经销商名称(在 Reseller.ID 上加入 Invoice.CustomerID)
3. 从 Job 表中获取关联的 Job ID(Job.InvoiceID 与 Invoice.ID 结合)
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 或其他任何东西。 我的目标是在我工作时将 output 转储到 HTML。

提前致谢。

它认为,如果您两次将左联接加入 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

我假设 Retailer 有一个名为 Name 的列,您也想返回它,请随时将其更改为 ID 或您希望返回的任何其他内容。

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

部分你想要 PIVOT 你的结果。 因此,您可以简单地将数据连接在一起,让 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 中的金额相乘...

DPMattingley 产生了一个很好的查询,但有一个限制 - 如果一个时间段没有结果,它根本不会显示一行。 在此处的特定示例中,这很可能不太可能发生,但是在确实发生的情况下,发现报告隐藏了零结果月份是很烦人的!

我对此的标准解决方案包括从数字表中获取月份,这会强制显示所有时间段。 使用 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM