如何从 MS SQL Server 中按日期范围过滤的不同表中获取聚合

问题描述

我正在编写要从 WebApi 调用的存储过程。这将是显示日期范围和其他过滤参数之间不同商店的不同 KPI 的摘要报告。为简单起见,假设我们只有日期范围作为过滤器。实际报表将有 30 多个列,其中大部分是来自不同表的聚合。

我需要有关如何处理此问题的帮助。我尝试过使用临时表(例如#temp)以及一些子查询。但是,我不确定实现这一目标的最佳方法是什么。

下面是一些虚拟表结构及其行和所需的输出。感谢所有建议和帮助。

生成虚拟数据的sql脚本

If(OBJECT_ID('tempdb..#Shops') Is Not Null)
Begin
    Drop Table #Shops
End
If(OBJECT_ID('tempdb..#Sales') Is Not Null)
Begin
    Drop Table #Sales
End
If(OBJECT_ID('tempdb..#refunds') Is Not Null)
Begin
    Drop Table #refunds
End
If(OBJECT_ID('tempdb..#Customers') Is Not Null)
Begin
    Drop Table #Customers
End


---Table: Shop
CREATE TABLE #Shops (
    ShopId Int,ShopName Varchar(20)
)
INSERT INTO #Shops (ShopId,ShopName) VALUES
  (1,'Manchester'),(2,'Liverpool 1'),(3,'Liverpool 2'),(4,'Leeds')

---Table: Sales
CREATE TABLE #Sales (
    SaleDate Date,ShopId Int,Qty Int,SValue decimal(13,2)
)

INSERT INTO #Sales (SaleDate,ShopId,Qty,SValue) VALUES
  ('01-Jan-2021',1,2,5.00),('05-Jan-2021',('02-Jan-2021',3,('06-Jan-2021',4,('07-Jan-2021',('09-Jan-2021',('10-Jan-2021',5.00)


---Table: refunds
CREATE TABLE #refunds (
    refundDate Date,RValue decimal(13,2)
)

INSERT INTO #refunds (refundDate,RValue) VALUES
  ('02-Jan-2021',2.00),3.00),1.50),2.25),0.50),1.50)

---Table: Customers
CREATE TABLE #Customers (
    CustId Int,RegShopId Int,RegisteredOn Date,CustomerName Varchar(20)
)

INSERT INTO #Customers (CustId,RegShopId,RegisteredOn,CustomerName) VALUES
  (1,'02-Jan-2021','Mr ABC'),'Mrs XYZ'),'05-Jan-2021','Mr PQR'),'08-Jan-2021','Mr MNO')  



--select ShopId,SUM(SValue) as TotalSaleValue,SUM(Qty) as TotalSaleQty from #Sales where SaleDate BETWEEN '5-Jan-2021' AND '15-Jan-2021' gROUP BY ShopId
--select ShopId,SUM(RValue) as TotalrefundValue,SUM(Qty) as TotalrefundValue from #refunds where refundDate BETWEEN '5-Jan-2021' AND '15-Jan-2021' gROUP BY ShopId
--select RegShopId,count(*) as NoOfNewCustomers  from #Customers where RegisteredOn BETWEEN '5-Jan-2021' AND '15-Jan-2021' gROUP BY RegShopId

我的尝试(它确实产生了想要的结果,但多了一行(利物浦 2)。此外,在生产中,我会创建 UDF 而不是子查询

SELECT 
    s.*,sl.SValue,sl.SQty,rf.RValue,rf.RQty,c.NoOfNewCusts
FROM 
    #Shops s 
    left JOIN   (
        SELECT 
            ShopId,SUM(sValue) SValue,SUM(Qty) SQty 
        FROM 
            #Sales 
        WHERE   SaleDate BETWEEN '5-Jan-2021' AND '15-Jan-2021' 
        GROUP BY shopid
        ) sl ON s.ShopId = sl.ShopId
    left JOIN   (
        SELECT 
            ShopId,SUM(RValue) RValue,SUM(Qty) RQty 
        FROM 
            #refunds
        WHERE refundDate BETWEEN '5-Jan-2021' AND '15-Jan-2021' 
        GROUP BY shopid
        ) rf ON s.ShopId = rf.ShopId
    LEFT JOIN   (
        SELECT 
            RegShopId,COUNT(*) NoOfNewCusts 
        FROM 
            #Customers
        WHERE RegisteredOn BETWEEN '5-Jan-2021' AND '15-Jan-2021' 
        GROUP BY RegShopId
        ) c ON s.ShopId = c.RegShopId

我的日期范围查询结果: 05-Jan-2021 和 15-Jan-2021

| ShopId | ShopName   | TotSalValue | TotSalQty | TotRefValue | TotRefQty | NoOfNewCustomers
| ------ | ---------- | ----------- | --------- | ----------- | --------- | ---------------- 
| 1      | Manchester | 10.00       | 4         |   4.25      |  2        |   1
| 2      | Liverpool 1| 20.00       | 8         |   7.00      |  3        |   1
| 3      | Liverpool 2| NULL        | NULL      |   NULL      |  NULL     |   NULL
| 4      | Leeds      | 10.00       | 4         |   4.50      |  2        |   0 OR NULL

日期范围的预期结果: 2021 年 1 月 5 日和 2021 年 1 月 15 日

| ShopId | ShopName   | TotSalValue | TotSalQty | TotRefValue | TotRefQty | NoOfNewCustomers
| ------ | ---------- | ----------- | --------- | ----------- | --------- | ---------------- 
| 1      | Manchester | 10.00       | 4         |   4.25      |  2        |   1
| 2      | Liverpool 1| 20.00       | 8         |   7.00      |  3        |   1
| 4      | Leeds      | 10.00       | 4         |   4.50      |  2        |   0 OR NULL

我想知道:

  • 这是正确的方法吗。
  • 如何去掉所有列中为 null 的商店。
  • UDF 是否会影响性能(在生产中,我有很多表可以进行子查询

谢谢

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...