我需要按区域检查长期日期(5年以上)的月销售额(非总和),类似于excel数据透视表,目前我正在Pandas上工作,但这里没有人使用它,所以我正在尝试为需要它的任何人在SQLServer中生成视图或存储过程。在此表中,存储了与某个区域相关联的销售数据,而该产品与之相关。
我可以列出区域,销售,月份和年份,并将其分组,但是正如我提到的,如果垂直对齐的月份或年份更容易阅读(每年大约有10万条记录,此时excel滞后)。
@pytest.fixture(scope='session')
def bc():
return BaseClass(...)
@pytest.fixture(scope='session')
def instance(request, bc):
cls = request.param
if cls.__name__ == 'BaseClass':
instance = bc
else:
instance = cls()
yield instance
Wich返回此:
CREATE TABLE SALESHS
(
IDAREA INT,
DATEREG [NVARCHAR](50) NOT NULL,
IDPROD [NVARCHAR](50) NOT NULL
);
GO
-- Insert rows into table 'SALESHS'
INSERT INTO SALESHS
(
IDAREA, DATEREG, IDPROD
)
VALUES
(
1, '12/03/2019', 'xplpc'
),
(
1, '15/03/2019', 'ndtlctm'
),
(
2, '12/04/2019', 'wntd'
)
GO
SELECT IDAREA,
COUNT(IDAREA) AS CANT,
DATEREG, --DATE AS DD/MM/YYYY
DATEPART(MM,CAST(DATEREG AS DATETIME)) AS MONTH,
DATEPART(YYYY,CAST(DATEREG AS DATETIME)) AS YEAR,
FROM saleshs
WHERE DATEREG > 201712
GROUP BY DATEREG , idarea
ORDER BY DATEREG
预期结果:
IDAREA AMOUNT MONTH YEAR PER_PRO
----------------------------------------
1 2 03 2019 201904
2 1 04 2019 201904
我知道sql的基础知识,也不希望得到完整的答案,但是任何可以帮助我建立此视图的内容都值得赞赏。我也尝试过PIVOT,但无法在同一查询中计算,区分和求和。
答案 0 :(得分:0)
您可以尝试Conditional Aggregation
SELECT IDAREA,
SUM( CASE WHEN YEAR(CAST(DATEREG AS DATETIME))= 2019 AND
MONTH(CAST(DATEREG AS DATETIME))=1 THEN
1
ELSE
0
END) JAN2019,
SUM( CASE WHEN YEAR(CAST(DATEREG AS DATETIME))= 2019 AND
MONTH(CAST(DATEREG AS DATETIME))=2 THEN
1
ELSE
0
END) FEB2019,
SUM( CASE WHEN YEAR(CAST(DATEREG AS DATETIME))= 2019 AND
MONTH(CAST(DATEREG AS DATETIME))=3 THEN
1
ELSE
0
END) MAR2019,
SUM( CASE WHEN YEAR(CAST(DATEREG AS DATETIME))= 2019 AND
MONTH(CAST(DATEREG AS DATETIME))=4 THEN
1
ELSE
0
END) APR2019
FROM saleshs
WHERE YEAR(CAST(DATEREG AS DATETIME))> 2017
GROUP BY IDAREA
ORDER BY IDAREA
答案 1 :(得分:0)
--Build the column names for Pivot using dynamic SQL
DECLARE @YourChoice date
set @YourChoice = '2017/12/13' --change here to what date you want the earliest
declare @count int = 0
declare @columnstr varchar(max)
declare @columnpivot varchar(max)
declare @onecolumnname varchar(20)
set @columnstr = ''
set @columnpivot = ''
set @onecolumnname = ''
while @count <= DATEDIFF(MONTH,@YourChoice,GETDATE())
begin
set @onecolumnname = concat(cast(datename(month,dateadd(month,@count,@YourChoice)) as varchar(50)),cast(year(dateadd(month,@count,@YourChoice)) as varchar(10)))
set @columnstr = @columnstr + 'coalesce([' + @onecolumnname+ '],0) as '+@onecolumnname+', '
set @columnpivot = @columnpivot + '['+@onecolumnname+'], '
set @count = @count + 1
end
set @columnstr = left(@columnstr,len(@columnstr)-1)
set @columnpivot = '('+left(@columnpivot,len(@columnpivot)-1)+')'
--Pivot time!
declare @str varchar(max)
set @str =
'select IDAREA,' + @columnstr +' from (
select count(s.idarea) as amount,IDAREA,columnname from (
select *,datename(month,cast(substring(datereg,7,4)+''-''+substring(datereg,4,2)+''-''+substring(datereg,1,2) as datetime)) + SUBSTRING(datereg,7,4) as columnname
from SALESHS )s
group by IDAREA,columnname)s1
pivot
(
max(s1.amount)
for s1.columnname in '+@columnpivot+'
) p'
exec (@str)
测试结果1('2017/12/13'):
测试结果2('2018/12/14'):
答案 2 :(得分:0)
我创建了一个动态SQL以解决此特定问题。可以调整查询以在结果中显示哪个YEAR
,在查询的Column
部分中计数哪个PIVOT
。我使用的日期格式位于查询MM/DD/YYYY
下方。
您可以运行代码 HERE
下面是SQL查询。
CREATE TABLE SALESHS
( IDAREA INT,
DATEREG date NOT NULL,
IDPROD [NVARCHAR](50) NOT NULL
);
/* Insert rows into table 'SALESHS' */
INSERT INTO SALESHS
( IDAREA, DATEREG, IDPROD)
VALUES
( 1, '03/12/2019', 'xplpc'),
( 1, '03/15/2019', 'ndtlctm'),
( 2, '04/12/2019', 'wntd')
/* Create Calendar Table to capture all the dates for first day of month from start Date to end date */
CREATE TABLE Calendar
(
[CalendarDate] DATE
,[MonthName] AS FORMAT(CONVERT(DATE, DATEADD(m, DATEDIFF(m, 0, CalendarDate), 0)), 'MMM-yyyy')
,[MonthNo] AS FORMAT(CalendarDate,'MM')
,[Year] AS FORMAT(CalendarDate,'yyyy')
,DateKey AS CONCAT(FORMAT(CalendarDate,'yyyy'), FORMAT(CalendarDate,'MM'))
)
DECLARE @Date DATE, @StartDate DATE, @EndDate DATE
SET @Date = '01/01/2012'
SET @StartDate = CONVERT(DATE, DATEADD(m, DATEDIFF(m, 0, @Date), 0)) /* Set Start date to first day of the month for given date */
SET @EndDate = '04/01/2019'
WHILE @StartDate <= @EndDate
BEGIN
INSERT INTO Calendar (CalendarDate)
SELECT @StartDate
SET @StartDate = DATEADD(m, 1, @StartDate)
END
/* Variable to hold unique Months to be used in PIVOT clause */
DECLARE @UniqueMonthsToPivot NVARCHAR(MAX) = N''
/* Extract unique Month names with pivot formattings */
SELECT @UniqueMonthsToPivot = @UniqueMonthsToPivot + ', [' + COALESCE(MonthName, '') + ']'
FROM (SELECT DISTINCT MonthName FROM Calendar) DT
/* Remove first comma and space */
SELECT @UniqueMonthsToPivot = LTRIM(STUFF(@UniqueMonthsToPivot, 1, 1, ''))
/* Variable to hold pivot column names with alias to be used in SELECT Clause */
DECLARE @PivotMonthsToSelect NVARCHAR(MAX) = N''
/* Generate column names list for SELECT list with SUM Function and NULL handling.
YEAR in the where condition can be adjust to select and show only certain year or month in Select list.
Order by CalendarDate is important to define the sequence of columns in the result */
SELECT @PivotMonthsToSelect = @PivotMonthsToSelect + ', SUM(ISNULL([' + COALESCE(MonthName, '') + '], 0)) AS [' + MonthName + ']'
FROM Calendar WHERE Year >= 2012
Order by CalendarDate
/* Variable to hold t-sql query */
DECLARE @SQLStatement NVARCHAR(MAX) = N''
/* Generate dynamic PIVOT query here */
SET @SQLStatement =
N'SELECT IDAREA'
+ @PivotMonthsToSelect +
'FROM (
SELECT *
,CASE WHEN IDAREA IS NULL THEN 0 ELSE 1 END AS IDAREA_Dup
FROM Calendar C
LEFT JOIN SALESHS S ON C.CalendarDate = CONVERT(DATE, DATEADD(m, DATEDIFF(m, 0, DATEREG), 0))
) AA
PIVOT
( SUM(IDAREA_Dup)
FOR MonthName IN ('+ @UniqueMonthsToPivot +')
) P
WHERE IDAREA IS NOT NULL
GROUP BY IDAREA
'
/* Check the generated dynamic t-sql PIVOT query below */
--PRINT (@SQLStatement)
/* Execute the generated dynamic t-sql PIVOT query below */
EXEC (@SQLStatement)