如何仅根据类似的列变量获取列的总和?请参阅给出的示例以进一步了解该问题。
这是示例数据:
Location TENANT Date Sales Area
AMALL Tenant1 1/1/2016 1,000.00 50
AMALL Tenant1 1/2/2016 0.00 50
AMALL Tenant1 1/3/2016 0.00 50
So on..
AMALL Tenant2 1/1/2016 500.00 60
AMALL Tenant2 1/2/2016 0.00 60
AMALL Tenant2 1/3/2016 0.00 60
So on..
AMALL Tenant1 2/1/2016 800.00 50
AMALL Tenant1 2/2/2016 200.00 50
AMALL Tenant1 2/3/2016 0.00 50
So on..
AMALL Tenant3 2/1/2016 600.00 50
AMALL Tenant3 2/2/2016 600.00 50
AMALL Tenant3 2/3/2016 0.00 50
So on..
如您所见,在一个给定的位置,其中包含两个或更多不同的租户。每个都有每日销售。此外,每个租户都有独特的平方米或面积。我想要实现的是下面的示例输出。
预期输出
Location Month Total Sales Total Area
Amall January 1,500.00 110
Amall February 2,200.00 100
请参阅给定的预期输出。根据结果,1,500是1月份的总销售额,包括TENANT 1和2(1000 + 500 = 1,500)的销售额,而总面积仅包括租户1和2的不同区域(50 + 60 = 110)
在2月份,只有租户1和3是贡献者,假设租户2已关闭且根本没有销售。
根据总销售额, 2,200 ,来自1000(租户1)和1200(租户3)。此次总面积 100 (租户1 50,租户3 50)。租户2的60面积值当然不包括在内,因为它在给定月份(2月)没有销售
当前,输出错误
Location Month Total Sales Total Area
Amall January 1,500.00 110
Amall February 2,200.00 50
根据应用的更新逻辑和代码,我能够使用我的代码上的Distinct命令更正1月总面积的输出,但是我在2月份不正确,只有50,从租户1开始应该是100租户3是不同的租户,应该总结他们各自的区域,因为我使用的是Distinct命令, 系统将他们的区域视为一个区域,因此不会总结他们的区域。
我怎样才能得到他们的总和,因为,Area来自单独的或不同的承租人
这是我更新的代码
SELECT location , tenant , a.date , sales, area
INTO #Temptable1
FROM SalesTable
SELECT tenants.location , months.number ,months.MonthName
,(sum(case when year(DATE) = 2016 then sales end)) as 'Total Sales'
,(sum(Distinct(case when year(DATE) = 2016 then area end))) as 'Total Area'
FROM
(
SELECT Number , DATENAME(MONTH, '2015-' + CAST(Number as varchar(2)) + '-1')
'MonthName'
FROM master..spt_values
WHERE Type = 'P' and Number between 1 and 12
) months
CROSS JOIN
(
SELECT DISTINCT locationd , location
FROM #TempTable1
) tenants
LEFT JOIN #TempTable1 t
ON months.monthname = datename(month,t.date) and tenants.location = t.location
GROUP BY months.monthname , tenants.location , months.number
ORDER BY datepart(MM,months.monthname + '01 2000');
我根据一位专家的建议在最后一行中加入了一个Distinct命令,仍未给出答案。
希望您就主要问题分享您的专家意见。
答案 0 :(得分:3)
这应该有效
为了能够测试和验证它,我创建了一个临时表
CREATE TABLE #Test
(
Location varchar(20),
Tenant varchar(20),
[Date] date,
Sales decimal,
Area int
)
INSERT INTO #TEST
SELECT 'AMALL', 'Tenant1', '1/1/2016', 1000.00, 50
UNION
SELECT 'AMALL', 'Tenant1', '1/2/2016', 0.00, 50
UNION
SELECT 'AMALL', 'Tenant1', '1/3/2016', 0.00, 50
UNION
SELECT 'AMALL', 'Tenant1', '1/4/2016', 0.00, 50
UNION
SELECT 'AMALL', 'Tenant1', '1/5/2016', 0.00, 50
UNION
SELECT 'AMALL', 'Tenant2', '1/1/2016', 500.00, 60
UNION
SELECT 'AMALL', 'Tenant2', '1/2/2016', 0.00, 60
UNION
SELECT 'AMALL', 'Tenant2', '1/3/2016', 0.00, 60
UNION
SELECT 'AMALL', 'Tenant2', '1/4/2016', 0.00, 60
UNION
SELECT 'AMALL', 'Tenant2', '1/5/2016', 0.00, 60
审核评论后的新解决方案
;WITH ATL(Area, Tenant, Location) AS
(
SELECT MAX(Area) Area, Tenant, Location
FROM #Test
GROUP BY Tenant, Location
),
AreaLocation(Area, Location)
AS
(
SELECT SUM(Area) Area, Location
FROM ATL
GROUP BY Location
)
SELECT
T.Location,
DATEPART(MONTH, T.[Date]) Month,
SUM(T.Sales) [Total Sales],
MAX(AL.Area) [Total Area]
FROM
#Test T
JOIN
AreaLocation AL ON T.Location = AL.Location
GROUP BY
T.Location, DATEPART(MONTH, [Date])
问题的旧解决方案:
SELECT
Location,
DATEPART(MONTH, [Date]) Month,
SUM(Sales) [Total Sales],
SUM(DISTINCT Area) [Total Area]
FROM
#Test
GROUP BY
Location, DATEPART(MONTH, [Date])
而且我也想放弃桌子,这样如果我做出更改,我就可以再次运行
DROP TABLE #Test
答案 1 :(得分:2)
我试图重现这个问题:
;WITH Temptable1 AS (
SELECT *
FROM (VALUES
('AMALL', 'Tenant1', '1/1/2016', 1000.00, 50),
('AMALL', 'Tenant1', '1/2/2016', 0.00, 50),
('AMALL', 'Tenant1', '1/3/2016', 0.00, 50),
('AMALL', 'Tenant2', '1/1/2016', 500.00, 60),
('AMALL', 'Tenant2', '1/2/2016', 0.00, 60),
('AMALL', 'Tenant2', '1/3/2016', 0.00, 60),
('AMALL', 'Tenant1', '2/1/2016', 800.00, 50),
('AMALL', 'Tenant1', '2/2/2016', 200.00, 50),
('AMALL', 'Tenant1', '2/3/2016', 0.00, 50),
('AMALL', 'Tenant3', '2/1/2016', 600.00, 50),
('AMALL', 'Tenant3', '2/2/2016', 600.00, 50),
('AMALL', 'Tenant3', '2/3/2016', 0.00, 50)
) as t([location], tenant, [date], sales, area)
)
SELECT tenants.location , months.number ,months.MonthName
,(sum(case when year(DATE) = 2016 then sales end)) as 'Total Sales'
,(sum(Distinct(case when year(DATE) = 2016 then area end))) as 'Total Area'
FROM
(
SELECT Number , DATENAME(MONTH, '2015-' + CAST(Number as varchar(2)) + '-1')
'MonthName'
FROM master..spt_values
WHERE Type = 'P' and Number between 1 and 12
) months
CROSS JOIN
(
SELECT DISTINCT location
FROM TempTable1
) tenants
LEFT JOIN TempTable1 t
ON months.monthname = datename(month,t.date) and tenants.location = t.location
GROUP BY months.monthname , tenants.location , months.number
ORDER BY datepart(MM,months.monthname + '01 2000');
我得到了:
location number MonthName Total Sales Total Area
AMALL 1 January 1500.00 110
AMALL 2 February 2200.00 50
AMALL 3 March NULL NULL
...
AMALL 12 December NULL NULL
2月必须100
,50
只有DISTINCT
。我的坏。
所以我删除DISTINCT
并添加CTE以获取您需要的区域:
;WITH cte AS (
SELECT [location],
tenant,
area,
DATEPART(month,[date]) as m,
ROW_NUMBER() OVER (PARTITION BY [location], tenant, DATEPART(month,[date]) ORDER BY [date]) as rn
FROM Temptable1
)
SELECT res.*,
SUM(c.area) as [Total Area]
FROM (
SELECT tenants.[location],
months.number,
months.[MonthName],
SUM(case when year(DATE) = 2016 then t.sales end) as [Total Sales]
FROM
(
SELECT Number,
DATENAME(MONTH, '2015-' + CAST(Number as varchar(2)) + '-1')as [MonthName]
FROM master..spt_values
WHERE Type = 'P' and Number between 1 and 12
) months
CROSS JOIN
(
SELECT DISTINCT [location]
FROM TempTable1
) tenants
LEFT JOIN TempTable1 t
ON months.[monthname] = datename(month,t.[date]) and tenants.[location] = t.[location]
GROUP BY months.[monthname] , tenants.[location] , months.number
) as res
OUTER APPLY (SELECT * FROM cte WHERE [location] = res.location and m = res.number and rn= 1) as c
GROUP BY res.[location], res.number,res.[MonthName]
,res.[Total Sales]
ORDER BY datepart(MM,res.[monthname] + '01 2000');
这个CTE产生了这个:
location tenant area m rn
AMALL Tenant1 50 1 1 --we need this area
AMALL Tenant1 50 1 2
AMALL Tenant1 50 1 3
AMALL Tenant1 50 2 1 --and this
AMALL Tenant1 50 2 2
AMALL Tenant1 50 2 3
AMALL Tenant2 60 1 1 --and this
AMALL Tenant2 60 1 2
AMALL Tenant2 60 1 3
AMALL Tenant3 50 2 1 -- and this
AMALL Tenant3 50 2 2
AMALL Tenant3 50 2 3
全部使用rn = 1
。然后使用您的结果和输出JOIN(OUTER APPLY)此CTE:
location number MonthName Total Sales Total Area
AMALL 1 January 1500.00 110
AMALL 2 February 2200.00 100
...
答案 2 :(得分:2)
基于GOFR1答案,这非常有帮助,我能够通过从现有代码中包含两行代码来得到答案。
SELECT location , tenant , a.date , sales, area,
, ROW_NUMBER() OVER (PARTITION BY location, tenantcode, DATEPART(month,[date]) ORDER BY a.date) as rn
INTO #Temptable1
FROM SalesTable
SELECT tenants.location , months.number ,months.MonthName
,(sum(case when year(DATE) = 2016 then sales end)) as 'Total Sales'
,(sum(case when year(DATE) =2016 and rn = 1 then area end)) as 'Total Area'
FROM
(
SELECT Number , DATENAME(MONTH, '2015-' + CAST(Number as varchar(2)) + '-1')
'MonthName'
FROM master..spt_values
WHERE Type = 'P' and Number between 1 and 12
) months
CROSS JOIN
(
SELECT DISTINCT locationd , location
FROM #TempTable1
) tenants
LEFT JOIN #TempTable1 t
ON months.monthname = datename(month,t.date) and tenants.location = t.location
GROUP BY months.monthname , tenants.location , months.number
ORDER BY datepart(MM,months.monthname + '01 2000');
刚刚添加了这些行
根据Gofr1的想法添加了该列
替换
(总和(不同((年(DATE)= 2016年,然后t.sqm结束)))))'总面积'
并且有效
答案 3 :(得分:1)
此表达式将日期截断为月边界:
DECLARE @VarStart date = '2001-01-01';
DATEADD(month, DATEDIFF(month, @VarStart, [date]), @VarStart)
您可以使用该月第一天的任何开始日期。 可以使用相同的方法将日期截断到任何其他边界(周,日,小时,分钟等)
依靠不同租户在样本数据中具有不同区域的事实是不明智的。
分别计算每月总计,然后在位置和月份上将它们连接在一起。
CTE_MonthlySales
计算每月每个位置的总销售额。
CTE_TenantAreas
返回每个租户在一个月内至少有一次销售的区域。这将在CTE_MonthlyAreas
中进一步分组,以获得一个月内销售额的总面积。
CTE_Months
会生成一个月份列表。
CTE_Locations
是所有不同位置的列表。
最终SELECT
(左)将所有内容加入。
WITH
CTE_MonthlySales
AS
(
SELECT
Location
,DATEADD(month, DATEDIFF(month, @VarStart, [date]), @VarStart) AS DateMonth
,SUM(Sales) AS TotalSales
FROM #TempTable1
GROUP BY
Location
,DATEADD(month, DATEDIFF(month, @VarStart, [date]), @VarStart)
)
,CTE_TenantAreas
AS
(
SELECT
Location
,Tenant
,DATEADD(month, DATEDIFF(month, @VarStart, [date]), @VarStart) AS DateMonth
,MIN(Area) AS TenantArea
FROM #TempTable1
WHERE Sales <> 0
GROUP BY
Location
,Tenant
,DATEADD(month, DATEDIFF(month, @VarStart, [date]), @VarStart)
)
,CTE_MonthlyAreas
AS
(
SELECT
Location
,DateMonth
,SUM(TenantArea) AS TotalArea
FROM CTE_TenantAreas
GROUP BY
Location
,DateMonth
)
,CTE_Months
AS
(
SELECT DATEADD(month, Number-1, '2016-01-01') AS DateMonth
FROM master..spt_values
WHERE Type = 'P' and Number between 1 and 12
)
,CTE_Locations
AS
(
SELECT
Location
FROM #TempTable1
GROUP BY
Location
)
SELECT
CTE_Locations.Location
,CTE_Months.DateMonth
,ISNULL(CTE_MonthlySales.TotalSales, 0) AS TotalSales
,ISNULL(CTE_MonthlyAreas.TotalArea, 0) AS TotalArea
FROM
CTE_Months
CROSS JOIN CTE_Locations
LEFT JOIN CTE_MonthlySales
ON CTE_MonthlySales.Location = CTE_Locations.Location
AND CTE_MonthlySales.DateMonth = CTE_Months.DateMonth
LEFT JOIN CTE_MonthlyAreas
ON CTE_MonthlyAreas.Location = CTE_Locations.Location
AND CTE_MonthlyAreas.DateMonth = CTE_Months.DateMonth
ORDER BY
CTE_Locations.Location
,CTE_Months.DateMonth
;