每年COUNT次月度销售

时间:2019-04-29 19:51:53

标签: sql-server tsql sql-server-2008 count

我需要按区域检查长期日期(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,但无法在同一查询中计算,区分和求和。

3 个答案:

答案 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

Demo

答案 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'):

DB<>Fiddle

测试结果2('2018/12/14'):

DB<>Fiddle

答案 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)