COUNT ежемесячные продажи за каждый год - PullRequest
0 голосов
/ 29 апреля 2019

Мне нужно проверять ежемесячные продажи (не считая суммы) по областям для длинных диапазонов дат (5+ лет), что-то вроде сводной таблицы Excel, в настоящее время я работаю над Pandas, но здесь никто не работает с этим, поэтому я пытаюсь сгенерировать представление или хранимую процедуру в SQLServer для всех, кому это требуется. В этой таблице хранятся продажи, связанные с областью и продуктом которой был.

Я могу перечислять и группировать ОБЛАСТИ, ПРОДАЖИ, МЕСЯЦ И ГОД, но, как я уже говорил, было бы легче читать, если бы месяцы или годы были выровнены по вертикали (существует около 100 тыс. Записей в год, и на этом этапе лаги превосходят ).

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

Ожидаемые результаты:

IDAREA JAN2019 FEB2019 MAR2019 APR2019
--------------------------------------
1            0       0       2       0
2            0       0       0       1

Я знаю основы sql и не ожидаю полного ответа, но все, что может помочь мне построить эту точку зрения, приветствуется. Я также пробовал PIVOT, но не могу подсчитать, различить и суммировать в одном запросе.

Ответы [ 3 ]

0 голосов
/ 30 апреля 2019
--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

0 голосов
/ 30 апреля 2019

Я создал динамический SQL для решения этой конкретной проблемы. Можно настроить запрос, для которого YEAR отображать в результате, а какой Column для подсчета в разделе PIVOT запроса. Формат даты в я использовал ниже запрос MM/DD/YYYY.

Вы можете запустить код ЗДЕСЬ

Ниже приведен 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)

0 голосов
/ 29 апреля 2019

Вы можете попробовать 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

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...