将SQL结果分为两个子级别
我正在使用Access前端屏幕和后端的SQL查询。我试图得到一个结果集,它分为两个级别:区域和月份,然后是该期间活动的客户总数的相关计数,有订单的客户和没有订单的客户都在用户选择的期间内 下面是正在使用的两个表 客户表A 订单表B 用户选择报告的开始日期和结束日期,例如2016年5月1日至2016年7月31日 我需要一个查询,该查询将评估客户开始日期是否在报告期内,并生成以下输出: 结果集 这件事我已经坚持了两个星期了。。请帮忙 如果有帮助的话,这就是我已经走了多远将SQL结果分为两个子级别,sql,ms-access,vba,Sql,Ms Access,Vba,我正在使用Access前端屏幕和后端的SQL查询。我试图得到一个结果集,它分为两个级别:区域和月份,然后是该期间活动的客户总数的相关计数,有订单的客户和没有订单的客户都在用户选择的期间内 下面是正在使用的两个表 客户表A 订单表B 用户选择报告的开始日期和结束日期,例如2016年5月1日至2016年7月31日 我需要一个查询,该查询将评估客户开始日期是否在报告期内,并生成以下输出: 结果集 这件事我已经坚持了两个星期了。。请帮忙 如果有帮助的话,这就是我已经走了多远 PARAMETERS
PARAMETERS startDt DateTime, endDt DateTime, loc Text ( 255 );
SELECT DISTINCT a.[Region] AS Region,
Format(b.[Orderdate],"MMM-YY") AS MonthOrder,
(Select Count(CMet.[clientID]) as cnt from
(SELECT distinct b.[orderID], Format(b.[order date],"MMM-YY")
as Contact_Month, a.[clientID], a.[Region]
FROM Client as a
INNER JOIN orders AS b ON a.[client ID] = b.[client id]
WHERE iif(isnull(loc),a.[REgion] like '*',instr (loc,a.[region]))
and (b.[orderdate] between startDt and endDt)
and (a.[Start date] < startDt)
GROUP BY a.[Region], Format(b.[order date],"MMM-YY"),
a.[clientID], a.[Region]
HAVING count(a.[clientID]) >=1) as CMet) AS Clients_Met,
(select count([client id]) from clients where
iif(isnull(loc),[region] like '*',instr (loc,[region])) and
client.[Start date] < startDt AS Total_Client,
(Total_Client-Clients_Met) AS Not_Met,
format(Clients_Met/iif(Total_Client =0,1,Total_Client),'##.##%') AS Met_Percentage
FROM clients AS a
INNER JOIN orders AS b ON a.[client ID]=b.[client id]
WHERE iif(isnull(loc),a.[region] like '*',instr (loc,a.[region]))
and (a.[Start date] < startDt
GROUP BY a.[region], Format(b.[order date],"MMM-YY")
HAVING count(a.[client id]) >=1
ORDER BY a.[region];
您可以使用join语句来检查日期,也可以使用BETWEEN操作。这里是示例和示例的链接 我尝试了下面的解决方案。其思想是在内部查询中进行分组,然后在外部查询中进行求和:
SELECT Region, Month, Count(ID) AS Clients, Sum(HasOrder) AS ClientsWithOrders,
[Clients]-[ClientsWithOrders] AS ClientsWithoutOrders
FROM (SELECT Region, CDate(Month([Order Date]) & "/1/" & Year([Order Date])) AS [Month],
ID, Max(IIf([Client ID]=[ID],1,0)) AS HasOrder
FROM Orders, Client
WHERE ((([Order Date])>=#5/1/2016# And
([Order Date])<DateAdd("d",1,#7/31/2016#)))
GROUP BY Region, CDate(Month([Order Date]) & "/1/" & Year([Order Date])), ID)
AS RegionMonthClient
GROUP BY Region, Month
困难在于我从你那里得到了不同的结果。例如,对于东部客户3,4,我看到一个客户在5月份有订单,另一个客户在7月份有订单,客户3
这种方法对您有用吗?连接是最基本的。在将3个不同的参数分为2个级别时,如何计算它们的数量。是否要添加三个参数?您可以使用类似这样的方法从表组中选择q1、sumq2、sumq3、sumq4、sumq2+sumq3+sumq4作为q5。我也尝试了求和函数,它给出了相同的结果集。是的,结果集可能不正确,因为我是手动执行的。让我试试这个方法,看看是否达到预期效果。无论如何谢谢你!!我想我理解你的逻辑,感觉它越来越接近我所需要的。现在的挑战是我的clientID是字母数字的,所以Max无法工作。我如何确保即使在同一个月内有多个订单,也只对客户进行一次计数?啊,我刚刚意识到最大值用于计算1。。我的错。。我会再复习一遍。我曾在生产数据库中尝试过这种方法,但不幸的是,由于连接的性质,这给了我一个数以百万计的结果集。我尝试使用diff-join类型,结果是不正确的。我们有大约10000个客户,每个月订购5-6次。还有其他建议吗?您可以尝试将选择行标题区域、月份的逻辑提取到单独的查询或表中。您还可以简化我的示例,只在客户和月份之间交叉连接,然后将连接留给订单。如果性能仍然是一个问题,也许其他人会有更好的建议。
Region | Month |Total Clients|Clients with Orders|Clients w/o Orders
North |May-2016| 2 | 1 | 1
North |Jun-2016| 2 | 0 | 2
North |Jul-2016| 2 | 1 | 1
East |May-2016| 0 | 0 | 0
East |Jun-2016| 0 | 0 | 0
East |Jul-2016| 1 | 1 | 0
West |May-2016| 2 | 1 | 1
West |Jun-2016| 2 | 0 | 2
West |Jul-2016| 2 | 1 | 1
South |May-2016| 2 | 0 | 2
South |Jun-2016| 2 | 0 | 2
South |Jul-2016| 2 | 1 | 1
PARAMETERS startDt DateTime, endDt DateTime, loc Text ( 255 );
SELECT DISTINCT a.[Region] AS Region,
Format(b.[Orderdate],"MMM-YY") AS MonthOrder,
(Select Count(CMet.[clientID]) as cnt from
(SELECT distinct b.[orderID], Format(b.[order date],"MMM-YY")
as Contact_Month, a.[clientID], a.[Region]
FROM Client as a
INNER JOIN orders AS b ON a.[client ID] = b.[client id]
WHERE iif(isnull(loc),a.[REgion] like '*',instr (loc,a.[region]))
and (b.[orderdate] between startDt and endDt)
and (a.[Start date] < startDt)
GROUP BY a.[Region], Format(b.[order date],"MMM-YY"),
a.[clientID], a.[Region]
HAVING count(a.[clientID]) >=1) as CMet) AS Clients_Met,
(select count([client id]) from clients where
iif(isnull(loc),[region] like '*',instr (loc,[region])) and
client.[Start date] < startDt AS Total_Client,
(Total_Client-Clients_Met) AS Not_Met,
format(Clients_Met/iif(Total_Client =0,1,Total_Client),'##.##%') AS Met_Percentage
FROM clients AS a
INNER JOIN orders AS b ON a.[client ID]=b.[client id]
WHERE iif(isnull(loc),a.[region] like '*',instr (loc,a.[region]))
and (a.[Start date] < startDt
GROUP BY a.[region], Format(b.[order date],"MMM-YY")
HAVING count(a.[client id]) >=1
ORDER BY a.[region];
SELECT Region, Month, Count(ID) AS Clients, Sum(HasOrder) AS ClientsWithOrders,
[Clients]-[ClientsWithOrders] AS ClientsWithoutOrders
FROM (SELECT Region, CDate(Month([Order Date]) & "/1/" & Year([Order Date])) AS [Month],
ID, Max(IIf([Client ID]=[ID],1,0)) AS HasOrder
FROM Orders, Client
WHERE ((([Order Date])>=#5/1/2016# And
([Order Date])<DateAdd("d",1,#7/31/2016#)))
GROUP BY Region, CDate(Month([Order Date]) & "/1/" & Year([Order Date])), ID)
AS RegionMonthClient
GROUP BY Region, Month