Splitting Column wise values into rows - sql-server

I have a table with year and month wise values at column level.
Table Structure
----------------
Franchise Year Month1 Month2 Month3 Month4 ....Month12
Need to fetch values of last six month values from current month through SQL. Can anybody help?
Eg. If I need last six months, It should be current year record with month2 and month1 values as well as 2013 record with Month12, Month11, Month10, Month9 values.

DECLARE #MonthStart date
DECLARE #yyyy char(4)
DECLARE #mmm char(3)
DECLARE #monthColumn varchar(7)
DECLARE #SQL nvarchar(max)
set #MonthStart = DATEADD(day,1-DAY(getdate()), getdate())
set #MonthStart = DATEADD(month,-6,#MonthStart )
SET #SQL = 'SELECT Franchise'
WHILE DATEDIFF(month,#MonthStart,GETDATE() )>0
BEGIN
SET #yyyy = DATENAME(yyyy,#MonthStart )
SET #mmm = DATENAME(mm,#MonthStart )
SET #monthColumn = 'Month'+convert(varchar(2),DATEpart(m,#MonthStart ))
SET #SQL = #SQL +',
SUM(CASE WHEN Year = '+#yyyy+' THEN ['+#monthColumn +'] ELSE NULL END) AS ['+#mmm+' '+#yyyy +']'
set #MonthStart = DATEADD(month,1,#MonthStart )
END
/*Substitute with the name of the table*/
SET #SQL = #SQL +'
FROM [TableName] '
/*For demonstration purposes show the SQL to be executes*/
PRINT #SQL
/*Try to Execute it */
EXEC (#SQL)
This will generate and execute a statement along the lines of
SELECT Franchise,
SUM(CASE WHEN Year = 2013 THEN [Month8] ELSE NULL END) AS [Aug 2013],
SUM(CASE WHEN Year = 2013 THEN [Month9] ELSE NULL END) AS [Sep 2013],
SUM(CASE WHEN Year = 2013 THEN [Month10] ELSE NULL END) AS [Oct 2013],
SUM(CASE WHEN Year = 2013 THEN [Month11] ELSE NULL END) AS [Nov 2013],
SUM(CASE WHEN Year = 2013 THEN [Month12] ELSE NULL END) AS [Dec 2013],
SUM(CASE WHEN Year = 2014 THEN [Month1] ELSE NULL END) AS [Jan 2014]
FROM [TableName]

Related

Execution fails for stored procedure

I have an issue with the procedure below.
Error is:
Msg 402, Level 16, State 1, Procedure Get_FormattedBankStatement, Line
87. The data types nvarchar and nvarchar are incompatible in the subtract operator.
USE [K2_Objects]
GO
/****** Object: StoredProcedure [K2RestSrv].[Get_FormattedBankStatement] Script Date: 2/27/2019 5:00:12 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [K2RestSrv].[Get_FormattedBankStatement]
--Declaring input parameter variable
#OpeningBalance Decimal(18,2),
#jsonValue nvarchar(max)
AS
BEGIN
DECLARE
#TotalCount nvarchar(150),
#MinRowNum int, #MaxRowNum int,
#DebitRecord nvarchar(150),
#CreditRecord nvarchar(150),
#NewBalance nvarchar(150),
#PreviousBalance nvarchar(150);
--Creating Temp Table #GetRowID
Create table #GetStatement
(ID int identity(1,1),
PostDate nvarchar(150),
TransDate nvarchar(150),
ValueDate nvarchar(150),
TransID nvarchar(150),
Narration nvarchar(max),
Debit nvarchar(150),
Credit nvarchar(150),
Balance nvarchar(150));
--Inserting into TempTable #GetStatement Temp Table, from the select statement
INSERT INTO #GetStatement
(PostDate,
TransDate,
ValueDate,
TransID,
Narration,
Debit,
Credit,
Balance)
SELECT
max(case when name='post_date' then convert(nvarchar(150),StringValue) else '' end) as [PostDate],
max(case when name='tran_date' then convert(nvarchar(150),StringValue) else '' end) as [TranDate],
max(case when name='value_date' then convert(nvarchar(150),StringValue) else '' end) as [ValueDate],
max(case when name='tran_id' then convert(nvarchar(150),StringValue) else '' end) as [TransID],
max(case when name='narration' then convert(nvarchar(150),StringValue) else '' end) as [Narration],
max(case when name='debit' then convert(nvarchar(150),StringValue) else '' end) as [Debit],
max(case when name='credit' then convert(nvarchar(150),StringValue) else '' end) as [Credit],
max(case when name='balance' then convert(nvarchar(150),StringValue) else '' end) as [Balance]
FROM parseJSON
(
#jsonValue
)
WHERE ValueType IN ('string','real','int','object','array') and Object_ID is NULL
GROUP BY parent_ID;
--Selecting the first and Last RowNum from the TempTable
SET #MinRowNum = (SELECT Min(ID) FROM #GetStatement)
SET #MaxRowNum = (SELECT Max(ID) FROM #GetStatement)
SET #PreviousBalance = #OpeningBalance;
WHILE #MinRowNum < #MaxRowNum
BEGIN
SET #DebitRecord = (SELECT Debit FROM #GetStatement WHERE ID = #MinRowNum);
SET #CreditRecord = (SELECT Credit FROM #GetStatement WHERE ID = #MinRowNum);
SET #NewBalance = (#PreviousBalance - (#DebitRecord + #CreditRecord));
UPDATE #GetStatement SET Balance = #NewBalance WHERE ID = #MinRowNum;
SET #PreviousBalance = (Select Balance from #GetStatement where ID = #MinRowNum);
SET #MinRowNum = (#MinRowNum + 1);
END
Select ID, PostDate,TransDate,ValueDate,TransID,Narration,Debit,Credit,Balance from #GetStatement;
END
GO
Thanks for the support and insights shared.
I was able to overcome the issue, by changing the data type for all areas where I had Decimal(18,2) to money. The variable #OpeningBalance Decimal(18,2) was changed to #OpeningBalance money
Same was done for #DebitRecord, #CreditRecord, #NewBalance, #PreviousBalance
Likewise, 'Coalesce' was used for the calculation of the new balance, by coalescing the PreviousBalance, the CreditRecord, and the DebitRecord.
Change These DECLARES:
#NewBalance nvarchar(150),
#PreviousBalance nvarchar(150);
To
#NewBalance DECIMAL(10,2),
#PreviousBalance DECIMAL(10,2);

How to modify temp table inside cursor?

I have temp table data in sql. I need modify data in that table.
Please find snapshot attached
I need to have a col having month data like for 01-03 jan-mar
this is code I have written. It's not working:
DECLARE #month VARCHAR(50) -- month
DECLARE #year VARCHAR(256) -- year
DECLARE #monthf VARCHAR(256) -- year
DECLARE #months VARCHAR(256) -- year
DECLARE db_cursor CURSOR FOR
SELECT months,[year] FROM #temp where len(months)>4
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #month,#year
WHILE ##FETCH_STATUS = 0
BEGIN
IF SUBSTRING(#month,0,3) = '01'
set #monthf='Jan'
ELSE IF SUBSTRING(#month,0,3) = '02'
set #monthf='Feb'
ELSE IF SUBSTRING(#month,0,3) = '03'
set #monthf='Mar'
ELSE IF SUBSTRING(#month,0,3) = '04'
set #monthf='Apr'
ELSE IF SUBSTRING(#month,0,3) = '05'
set #monthf='May'
ELSE IF SUBSTRING(#month,0,3) = '06'
set #monthf='Jun'
ELSE IF SUBSTRING(#month,0,3) = '07'
set #monthf='Jul'
ELSE IF SUBSTRING(#month,0,3) = '08'
set #monthf='Aug'
ELSE IF SUBSTRING(#month,0,3) = '09'
set #monthf='Sep'
ELSE IF SUBSTRING(#month,0,3) = '10'
set #monthf='Oct'
ELSE IF SUBSTRING(#month,0,3) = '11'
set #monthf='Nov'
ELSE IF SUBSTRING(#month,0,3) = '12'
set #monthf='Dec'
IF SUBSTRING(#month,4,2) = '01'
set #months='Jan'
ELSE IF SUBSTRING(#month,4,2) = '02'
set #months='Feb'
ELSE IF SUBSTRING(#month,4,2) = '03'
set #months='Mar'
ELSE IF SUBSTRING(#month,4,2) = '04'
set #months='Apr'
ELSE IF SUBSTRING(#month,4,2) = '05'
set #months='May'
ELSE IF SUBSTRING(#month,4,2) = '06'
set #months='Jun'
ELSE IF SUBSTRING(#month,4,2) = '07'
set #months='Jul'
ELSE IF SUBSTRING(#month,4,2) = '08'
set #months='Aug'
ELSE IF SUBSTRING(#month,4,2) = '09'
set #months='Sep'
ELSE IF SUBSTRING(#month,4,2) = '10'
set #months='Oct'
ELSE IF SUBSTRING(#month,4,2) = '11'
set #months='Nov'
ELSE IF SUBSTRING(#month,4,2) = '12'
set #months='Dec'
update #temp set [Month]= where months=
Delete from #temp where months=SUBSTRING(#month,0,3) and [Year]=#year
Delete from #temp where months=SUBSTRING(#month,4,2) and [Year]=#year
FETCH NEXT FROM db_cursor INTO #month,#year
END
CLOSE db_cursor
DEALLOCATE db_cursor
I need another column with month names like: for 01-03 it should give jan-mar
Can you please help me out? I need a separate column for month string data.
You don't need a cursor at all.
IF OBJECT_ID('tempdb..#Data') IS NOT NULL
DROP TABLE #Data
CREATE TABLE #Data (
Month VARCHAR(100),
ResultMonthText VARCHAR(100))
INSERT INTO #Data (
Month)
VALUES
('01-03'),
('07'),
('03'),
('03-05'),
('05-09'),
('02')
;WITH ParsedMonths AS
(
SELECT
D.Month,
D.ResultMonthText,
First = CONVERT(INT, SUBSTRING(D.Month, 1, 2)),
Second = CONVERT(INT, NULLIF(SUBSTRING(D.Month, 4, 2), ''))
FROM
#Data AS D
),
MonthNames AS
(
SELECT
D.Month,
D.ResultMonthText,
FirstAsName = SUBSTRING(
DATENAME(
MONTH,
DATEADD(MONTH, D.First, 0) - 1 ),
1,
3),
SecondAsName = SUBSTRING(
DATENAME(
MONTH,
DATEADD(MONTH, D.Second, 0) - 1 ),
1,
3)
FROM
ParsedMonths AS D
)
UPDATE D SET
ResultMonthText = D.FirstAsName + ISNULL('-' + D.SecondAsName, '')
FROM
MonthNames AS D
SELECT
*
FROM
#Data AS D
/*
Result:
Month ResultMonthText
------- ------------
01-03 Jan-Mar
07 Jul
03 Mar
03-05 Mar-May
05-09 May-Sep
02 Feb
*/
EDIT: Do this if you still want to keep your cursor (although I strongly suggest you stop using them whenever you can):
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #month,#year
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #FirstMonthNumber INT = CONVERT(INT, SUBSTRING(#month, 1, 2))
DECLARE #SecondMonthNumber INT = CONVERT(INT, NULLIF(SUBSTRING(#month, 4, 2), ''))
DECLARE #FirstMonthText VARCHAR(10) = SUBSTRING(
DATENAME(
MONTH,
DATEADD(MONTH, #FirstMonthNumber, 0) - 1 ),
1,
3)
DECLARE #SecondMonthText VARCHAR(10) = SUBSTRING(
DATENAME(
MONTH,
DATEADD(MONTH, #SecondMonthNumber, 0) - 1 ),
1,
3)
update #temp set
YourNewMonthColumn = #FirstMonthText + ISNULL('-' + #SecondMonthText, '')
WHERE
months = #month
FETCH NEXT FROM db_cursor INTO #month,#year
END
I don't know why you update the column and then delete the row also.
Maybe
update #temp set [Month] = #monthf where months = #months

SQL Server Row Into Column

We have a table showing amounts (CHGCNT) for 3 dates (5-9-2016, 5-10-2016, 5-11-2016) for each store & Depts.
I want to be able to see the records in a table like this:
I already applied the following query
declare #dt as datetime
declare #dt1 as varchar(10)
declare #dt2 as varchar(10)
declare #dt3 as varchar(10)
select distinct #dt = min(effdt) from [HQExtract].[dbo].[FSM_PRICE_TAGCOUNT]
-- print CONVERT(CHAR(10), #dt, 110) + ' ---- ' + CONVERT(CHAR(10), #dt+1 , 110)
set #dt1 = CONVERT(CHAR(10), #dt, 110)
set #dt2 = CONVERT(CHAR(10), #dt +1 , 110)
set #dt3 = CONVERT(CHAR(10), #dt + 2 , 110)
--print #dt1 + ' ---- ' + #dt2 + '-----' + #dt3
SELECT DEPTNM, DEPT, [#dt1] , [#dt2] , [#dt3]
FROM [HQExtract].[dbo].[FSM_PRICE_TAGCOUNT]
PIVOT
(
SUM(CHGCNT)
FOR effdt IN ( [#dt1] , [#dt2] , [#dt3])
) AS P
but it is returning dates
I like the SUM-CASE approach:
SELECT deptnm,
SUM(CASE WHEN effdt = '2016-05-09' THEN chgcnt ELSE 0 END) "2016-05-09",
SUM(CASE WHEN effdt = '2016-05-10' THEN chgcnt ELSE 0 END) "2016-05-10",
SUM(CASE WHEN effdt = '2016-05-11' THEN chgcnt ELSE 0 END) "2016-05-11",
SUM(effdt) Total
FROM [HQExtract].[dbo].[FSM_PRICE_TAGCOUNT]
GROUP BY deptnm;

Displaying results based on different selection in sql server stored procedure

I am currently working on Microsoft SQL Server 2008. My question is: I have 5 conditions represented by parameters #rep, #name, #work, #year, #seg. How do I write a query that will display the result if I only fill up certain conditions=? And then I have a query that will count total number of visit. For example,
DECLARE #Rep varchar(100)
DECLARE #Name varchar(100)
DECLARE #Work varchar (100)
DECLARE #Year int
DECLARE #Seg int
SET #RepCode = ''
SET #Name = 'SYED'
SET #Work = ''
SET #Year = '2014'
SET #Seg = ''
I want the result to display the result for syed with year 2014 and the rep, work, and his seg. I tried this but it didn't work out.
if #Rep IS NOT NULL
SELECT Id, Name, Work, YEAR, Rep
FROM #SalesRepVisit
WHERE Rep = #Rep
ELSE
if #Name IS NOT NULL
SELECT Id, Name, Work, YEAR, Rep
FROM #SalesRepVisit
WHERE Name = #Name
ELSE
if #Work IS NOT NULL
SELECT Id, Name, Work, YEAR, Rep
FROM #SalesRepVisit
WHERE Work = #Work
ELSE
if #Year IS NOT NULL
SELECT Id, Name, Work, YEAR, Rep
FROM #SalesRepVisit
WHERE YEAR = #Year
ELSE
if #Seg IS NOT NULL
SELECT Id, Name, Work, YEAR, Rep
FROM #SalesRepVisit
WHERE Seg = #Seg
To count the total number of visit I have this query.
SELECT DISTINCT
Id as Id,
Name as Customername,
Rep As Repcode,
(Select COUNT(*) from #SalesRepVisit where Month = 1 and Rep = #Rep and Name = #Name AND Work = #Work and YEAR = #Year)as 'January',
(Select COUNT(*) from #SalesRepVisit where Month = 2 and Rep = #Rep and Name = #Name AND Work = #Work and YEAR = #Year)as 'February',
(Select COUNT(*) from #SalesRepVisit where Month = 3 and Rep = #Rep and Name = #Name AND Work = #Work and YEAR = #Year)as 'March' ,
(Select COUNT(*) from #SalesRepVisit where Month = 4 and Rep = #Rep and Name = #Name AND Work = #Work and YEAR = #Year)as 'April',
(Select COUNT(*) from #SalesRepVisit where Month = 5 and Rep = #Rep and Name = #Name AND Work = #Work and YEAR = #Year)as 'May',
(Select COUNT(*) from #SalesRepVisit where Month = 6 and Rep = #Rep and Name = #Name AND Work = #Work and YEAR = #Year)as 'June',
(Select COUNT(*) from #SalesRepVisit where Month = 7 and Rep = #Rep and Name = #Name AND Work = #Work and YEAR = #Year)as 'July',
(Select COUNT(*) from #SalesRepVisit where Month = 8 and Rep = #Rep and Name = #Name AND Work = #Work and YEAR = #Year)as 'August',
(Select COUNT(*) from #SalesRepVisit where Month = 9 and Rep = #Rep and Name = #Name AND Work = #Work and YEAR = #Year)as 'September',
(Select COUNT(*) from #SalesRepVisit where Month = 10 and Rep = #Rep and Name = #Name AND Work = #Work and YEAR = #Year)as 'October',
(Select COUNT(*) from #SalesRepVisit where Month = 11 and Rep = #Rep and Name = #Name AND Work = #Work and YEAR = #Year)as 'November',
(Select COUNT(*) from #SalesRepVisit where Month = 12 and Rep = #Rep and Name = #Name AND Work = #Work and YEAR = #Year)as 'December',
Work as Work,
YEAR as Year
FROM #SalesRepVisit
WHERE
Rep = #Rep and Name = #Name AND Work = #Work AND YEAR = #Year
The query doesn't display anything. I want the query to display the results of 'syed' with his name, rep, work, seg, and year.
Improved Answer of #Radar
In the Where condition we can use Case statement
SELECT Id,
Name,
SUM ( CASE WHEN Month =1 THEN 1 ELSE 0 END ) as 'January',
SUM ( CASE WHEN Month =2 THEN 1 ELSE 0 END ) as 'February',
...
...
FROM #SalesRepVisit
where ( Rep = Case When IsNull(#RepCode,'') ='' then Rep else #RepCode end)
AND ( Name = Case When IsNull(#Name,'')='' then Name else #Name end)
AND ( Work = Case When IsNull(#Work,'') ='' then Work else #Work end)
AND ( YEAR = Case When IsNull(#Year,'') ='' then YEAR else #Year end)
GROUP BY Id, Name
you are setting default value to empty string and comparing with NOT NULL as empty string is NOT NULL, search is done for empty string.
First part to get results when only filters condition is met
SELECT Id,Name,Work,YEAR,Rep from #SalesRepVisit
WHERE ( #RepCode ='' OR Rep = #RepCode )
AND ( #Name ='' OR Name = #Name )
AND ( #Work ='' OR Work = #Work )
AND ( #Year ='' OR YEAR = #Year )
To count the number of visits in each Month based on the filter criteria, you can use case based aggregation
SELECT Id,
Name,
SUM ( CASE WHEN Month =1 THEN 1 ELSE 0 END ) as 'January',
SUM ( CASE WHEN Month =2 THEN 1 ELSE 0 END ) as 'February',
...
...
FROM #SalesRepVisit
where ( #RepCode ='' OR Rep = #RepCode )
AND ( #Name='' OR Name = #Name )
AND ( #Work ='' OR Work = #Work )
AND ( #Year ='' OR YEAR = #Year )
GROUP BY Id, Name

how to include the parameter name as the name of a column in sql

I have a stored procedure that looks something like this :
CREATE PROCEDURE [dbo].[spRS_Get]
#Year Varchar(20),
#Month Varchar(20)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Paramdate datetime;
DECLARE #ParamYear varchar(4);
DECLARE #ParamMonth varchar(2);
DECLARE #Concatt varchar(10);
SET #ParamYear = #Year;
SET #ParamMonth = #Month;
SET #Concatt = #ParamMonth + '-' + '01' + '-' + #ParamYear;
SET #Paramdate = CONVERT(datetime, #Concatt);
SELECT Item
,SUM(CASE WHEN [MONTH] = month(#ParamDate) THEN Sales END) AS month(#ParamDate)
,SUM(CASE WHEN [MONTH] = month(#ParamDate) - 1 THEN Sales END) AS month(#ParamDate) - 1,
,SUM(CASE WHEN [MONTH] = month(#ParamDate) THEN Sales END) - SUM(CASE WHEN [MONTH] = month(#ParamDate) - 1 THEN Sales END) AS month(#ParamDate) - month(#ParamDate) - 1
FROM ABC
GROUP BY Item
In the above query , the part after the AS causes the error.
I want to use the parameter name as the name of the column , but it gives me an error. Is there a way I can use
the parameter name as the name of the month ?
You can only do that by building the select statement as a string and then executing it using the sp_executesql command.
So you'd get something like this:
declare #month0 varchar(2) = cast(month(#paramdate) as varchar(2));
declare #month1 varchar(2) = cast((month(#ParamDate) - 1) as varchar(2));
declare #month2 varchar(2) =
cast((month(#ParamDate) - month(#ParamDate) - 1) as varchar(2));
declare s nvarchar(1024) =
'SELECT Item
, SUM(CASE WHEN [MONTH] = month(#d) THEN Sales END)
AS ''' + #month0 +
''' , SUM(CASE WHEN [MONTH] = month(#d) - 1 THEN Sales END)
AS ''' + #month1 +
''' , SUM(CASE WHEN [MONTH] = month(#d) THEN Sales END) -
SUM(CASE WHEN [MONTH] = month(#d) - 1 THEN Sales END)
AS ''' + #month2 +
''' FROM ABC GROUP BY Item';
EXEC sp_executesql #s, N'#d DATETIME', #ParamDate;

Resources