Creating a TABLE to pivot and concat columns from exiting table? - sql

I have a Table that stores customer Dynamic values from the Forms that they create.
The Table is called Dynamic_Fields_T and is formatted like this:
ID | FIELD_NAME
1 | TANK
2 | PRODUCT TYPE
3 | ODOMETER
4 | RECEIPT #
This is not joinable to our ticket Tables.
I need this to appear like this:
ID_1 | ID_2 .......ID_N
TANK | PRODUCT_TYPE ......N
Any Help is appreciated.

Assuming that your [ID] column is unique you can use a dynamic select statement with an aggregation function (min or max) to return all your rows in a single row:
--create test table
create table #Dynamic_Fields_T (
[ID] INT
,[FIELD_NAME] varchar(max)
)
--populate test table
insert into #Dynamic_Fields_T
values
(1 ,'TANK')
,(2 ,'PRODUCT TYPE')
,(3 ,'ODOMETER')
,(4 ,'RECEIPT #')
declare #sql nvarchar(max) =''
--build dynamic columns
select
#sql = #sql + ',max(case when [ID] = ''' + cast([ID] as varchar) + ''' then [FIELD_NAME] end) as [ID_' + cast([ID] as varchar) + ' ] '
from
#Dynamic_Fields_T
--build dynamic query, remove unnecessary comma
select #sql = 'select ' + stuff(#sql, 1 , 1, '') + ' from #Dynamic_Fields_T'
--execute dynamic query
execute (#sql)
result:

Related

Dynamically create table columns with values from Pivot Table

I have a dynamic query that utilizes a pivot function and the following is an example of data in my table.
Status 1 | Week 1 |25
Status 1 | Week 1 |25
Status 1 | Week 2 |25
Status 2 | Week 1 | 2
Status 2 | Week 1 | 8
Status 2 | Week 1 | 10
Status 2 | Week 1 | 10
and this is an example of how the data is returned.
Week 1 Week 2
Status 1 | 50 25
Status 2 10 20
For my query I am passing in a week and I want to pivot on the following 5 weeks, so example, if I pass in 1, I expect to have columns from week 1 to week 6.
To help facilitate that I have written the following query.
--EXEC usp_weekReport #weeks=1, #year='2019'
ALTER PROC usp_weekReport
(
#weeks INT,
#year NVARCHAR(4)
)
AS
DECLARE #columns NVARCHAR(MAX), #sql NVARCHAR(MAX), #csql NVARCHAR(MAX);
SET #columns = N'';
SELECT #columns += N', p.' + QUOTENAME([week])
FROM (
SELECT p.[week]
FROM [Housing_support_DB].[dbo].[Invoices] P
WHERE DATEPART(YEAR,P.date)='2019'--#year
AND
([week] IN (1)
OR
[week] IN (1+1)
OR
[week] IN (1+2)
OR
[week] IN (1+3)
OR
[week] IN (1+4)
OR
[week] IN (1+5)
)
GROUP BY P.[week]
) AS x;
SET #sql = N'
SELECT p.[statusName],' + STUFF(#columns, 1, 2, '') + '
FROM
(
SELECT
SUM(CAST(REPLACE(REPLACE(A.amount,'','',''''),''$'','''') AS FLOAT)) as sumInvoice,
A.invoiceStatusID_FK,
B.statusName,
-- C.programme,
[week]
FROM [dbo].[Invoices] A
INNER JOIN invoiceStatus B
ON A.invoiceStatusID_FK=B.invoiceStatusID
-- INNER JOIN CapitalAccountBalances C
-- ON C.accountBalanceID=A.accountBalanceID_FK
-- WHERE A.accountBalanceID_FK=5
GROUP BY invoiceStatusID_FK,B.statusName,[week]--,C.programme
) AS j
PIVOT
(
SUM(sumInvoice) FOR [week] IN ('
+ STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '')
+ ')
) AS p;';
--PRINT #sql;
EXEC sp_executesql #sql;
--SET #csql = N'
--CREATE TABLE ##reportResult
--(
--statusName nvarchar(50),'+
CREATE TABLE ##reportResult
(
statusName nvarchar(50),
weekA INT DEFAULT 0,
weekB int DEFAULT 0--,
--weekC int DEFAULT 0,
--weekD int DEFAULT 0,
--weekE int DEFAULT 0,
--weekF int DEFAULT 0
)
INSERT into ##reportResult Exec(#sql)
--INSERT ##reportResult Exec(#sql)
--SELECT statusName, weekA,weekB,weekC,weekD,weekE,weekF -- here you have "static SELECT with field names"
--FROM ##reportResult
--DROP TABLE ##reportResult
Problem
The huge problem that I have here is that, I need to send the result of this query to a tempTable...#reportResult. As a result, I need to create the table. However, if I attempt to create the table with the max amount of columns anticipated (6) I will get an invalid number of columns error. For example, in my database I only have two weeks, that's why I can only create the table with columns weekA and weekB. I also cannot do a select into.
Presently, I am trying to find a way to either create the table dynamically depending on the amount of weeks from the first part of the pivot table. Or, to manipulate the first part of the pivot to select week,week+1 etc as columns when run so that way , I can create the column with all fields.
Appreciate any help that could be provided.
You required dynamic SQL in your case as the column name is need to generate based on th Input week number. Below I have give you the script I created with your sample data using CTE. You just need to updated the script based on your table and requirement.
You can test the code changing the value of Week_No
For your final query, just use the SELECT part after removing the CTE code
DECLARE #Week_No INT = 2
DECLARE #Loop_Count INT = 1
DECLARE #Column_List VARCHAR(MAX) = '[Week '+CAST(#Week_No AS VARCHAR) +']'
WHILE #Loop_Count < 5
BEGIN
SET #Column_List = #Column_List +',[Week '+CAST(#Week_No+#Loop_Count AS VARCHAR) +']'
SET #Loop_Count = #Loop_Count + 1
END
--SELECT #Column_List
EXEC
('
WITH your_table(Status,Week_No,Val)
AS
(
SELECT ''Status 1'',''Week 1'',25 UNION ALL
SELECT ''Status 1'',''Week 1'',25 UNION ALL
SELECT ''Status 1'',''Week 2'',25 UNION ALL
SELECT ''Status 2'',''Week 1'',2 UNION ALL
SELECT ''Status 2'',''Week 1'',8 UNION ALL
SELECT ''Status 2'',''Week 1'',10 UNION ALL
SELECT ''Status 2'',''Week 1'',10
)
SELECT * FROM
(
SELECT * FROM your_table
) AS P
PIVOT
(
SUM(val)
FOR Week_No IN ('+#Column_List+')
)PVT
')

Pivot SQL query output

I have a requirement where my query will return output something like this:
PermissionType IsAllowed
-------------------------
IsEdit | 1
IsDelete | 0
isRemove | 1
isPrint | 1
isReport | 0
-- | -
-- | -
-- | -
--------------------------
These rows can be dynamic depending upon the filter criteria I will pass.
So now I want to convert the above resultset to the following:
IsEdit | IsDelete | IsRemove | IsPrint | IsReport | -- | -- | --
--------------------------------------------------------------------
1 | 0 | 1 | 1 | 0 | - | - | -
I tried to use the pivot here but it asks the Column Names to be pivoted into the output and this is dynamic in my case, also it needed an aggregate function for FOR but I don't have any calculation in my case.
Anyone please help me on this.
Then try this Dynamic sql
IF OBJECT_ID('dbo.temp')IS NOT NULL
DROP TABLE temp
;WITH Cte(PermissionType, IsAllowed)
AS
(
SELECT 'IsEdit' , 1 UNION ALL
SELECT 'IsDelete' , 0 UNION ALL
SELECT 'isRemove' , 1 UNION ALL
SELECT 'isPrint' , 1 UNION ALL
SELECT 'isReport' , 0
)
SELECT *,ROW_NUMBER()OVER(ORDER BY (SELECT 1)) AS Seq INTO
temp FROM Cte
DECLARE #Sql nvarchar(max),
#Sqlcol nvarchar(max),
#ISNULLSqlcol nvarchar(max)
SELECT #Sqlcol=STUFF((SELECT ', '+QUOTENAME(PermissionType)
FROM temp ORDER BY Seq FOR XML PATH ('')),1,1,'')
SELECT #ISNULLSqlcol=STUFF((SELECT ', '+'MAX('+QUOTENAME(PermissionType) +') AS '+QUOTENAME(PermissionType)
FROM temp ORDER BY Seq FOR XML PATH ('')),1,1,'')
SET #Sql='
SELECT '+#ISNULLSqlcol+'
FROM(
SELECT * FROM temp
)AS SRC
PIVOT
(
MAX(IsAllowed) FOR PermissionType IN ('+#Sqlcol+')
) AS PVT '
PRINT #Sql
EXEC (#Sql)
IsEdit IsDelete isRemove isPrint isReport
--------------------------------------------------
1 0 1 1 0
With pivot and dynamic sql you can create a query that will include a different number of columns:
if OBJECT_ID('Test') is not null
drop table [dbo].[Test]
CREATE TABLE [dbo].[Test](PermissionType varchar(20), IsAllowed int)
insert into [dbo].[Test] values
('IsEdit' , 1)
,('IsDelete', 0)
,('isRemove', 1)
,('isPrint' , 1)
,('isReport', 0)
--this variable holds all the dates that will become column names
declare #permissionTypes nvarchar(max) = ''
--this variable contains the TSQL dinamically generated
declare #sql nvarchar(max) = ''
select #permissionTypes = #permissionTypes + ', ' + quotename(PermissionType)
from [dbo].[Test]
set #permissionTypes = RIGHT(#permissionTypes, len(#permissionTypes)-2)
set #sql = concat(
'select *
from [dbo].[Test]
pivot
(
max(isallowed)
for PermissionType in (', #permissionTypes, ')
) piv '
)
exec(#sql)
Result:
Adding a new row:
insert into [dbo].[Test] values
('IsNew' , 1)
Causes a new column to be created:

T-Sql Query with dynamic (unknown) number of columns

We have a project where we should provide the possible to the user to add own custom columns to various tables.
Edit: these are 2 tables, not one.
**Products**
ProductId
Name
Price
Date
UserId
**ProductsCustomColumns**
ProductId
ColumnName
ColumnValue
EDIT: Please note that the dynamic columns are recorded as values and we don't know the count of these...it can be 0 or 200 or any.
Here is an example:
Now when we query the products tables we want to show all the predefined columns and after them all custom columns.
Obviously each user can have own number of columns with values and names.
SELECT *, (and the custom columns) FROM Products WHERE UserId = 3 AND ProductId = 1
Here are 2 questions:
Would that be good solution from performance point of view or there is better approach for solving the dynamic columns requirement?
How can I create a query that could read all records from ProductsCustomColumns for given userId and productId and append the records as columns to the query?
Thanks.
You need to write dynamic Query
DECLARE #COLUMNS VARCHAR(MAX)='', #QRY VARCHAR(MAX);
SELECT #COLUMNS = #COLUMNS +COLUMN_NAME +',' FROM
INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='Products'
SELECT #COLUMNS =SUBSTRING (#COLUMNS,1 ,LEN(#COLUMNS)-1)
SELECT #QRY ='SELECT '+#COLUMNS + ' FROM Products WHERE UserId = 3 AND ProductId = 1'
EXEC (#QRY)
EDIT: From your Comments & Edited Question
Schema I assumed from your Question
CREATE TABLE Products (
ProductId INT,
Name VARCHAR(250),
Price DECIMAL(18,2),
DateS DATETIME,
UserId INT)
INSERT INTO Products
SELECT 1,'Oil Product', 2000, GETDATE(), 3
UNION ALL
SELECT 2,'Amway', 600, GETDATE(), 2
UNION ALL
SELECT 3,'Thermal', 5000, GETDATE(), 1
UNION ALL
SELECT 4,'Oil Product', 500, GETDATE(), 4
CREATE TABLE ProductsCustomColumns
(
ProductId INT ,
ColumnName VARCHAR(200),
ColumnValue VARCHAR(15))
INSERT INTO ProductsCustomColumns
SELECT 1, 'Licence_No', '1545'
UNION ALL
SELECT 1, 'Location ', 'Atlanta'
UNION ALL
SELECT 2, 'Qty ', '5'
UNION ALL
SELECT 3, 'Gross', '80000'
Now your Dynamic Code goes here
DECLARE #COLUMN_PCC VARCHAR(MAX)='', #PRODUCT_ID INT=1,#USER_ID INT=3, #QRY VARCHAR(MAX) ;
--preparing Custom Column Name List with comma ','
SELECT #COLUMN_PCC = #COLUMN_PCC+ [COLUMNNAME] +',' FROM ProductsCustomColumns
WHERE ProductId= #PRODUCT_ID
SELECT #COLUMN_PCC =SUBSTRING(#COLUMN_PCC,1,LEN(#COLUMN_PCC)-1)
--Preparing Dynamic Query
SELECT #QRY =' SELECT P.*, AV.* FROM Products P
INNER JOIN
(
SELECT * FROM (
SELECT * FROM ProductsCustomColumns WHERE ProductId= '+CAST(#PRODUCT_ID AS VARCHAR(50))+'
)
AS A
PIVOT
(
MAX (COLUMNVALUE)
FOR [COLUMNNAME] IN ('+#COLUMN_PCC +')
)AS PVT
)AS AV ON P.ProductId= AV.ProductId
AND P.UserId='++CAST(#USER_ID AS VARCHAR(50))+'
'
EXEC ( #QRY)
And the Result will be
+-----------+-------------+---------+-------------------------+--------+-----------+------------+----------+
| ProductId | Name | Price | DateS | UserId | ProductId | Licence_No | Location |
+-----------+-------------+---------+-------------------------+--------+-----------+------------+----------+
| 1 | Oil Product | 2000.00 | 2016-12-09 18:06:24.090 | 3 | 1 | 1545 | Atlanta |
+-----------+-------------+---------+-------------------------+--------+-----------+------------+----------+
You need dynamic sql no other way to do this
DECLARE #sql VARCHAR(max),
#cust_col VARCHAR(max)
SET #cust_col = (SELECT Quotename(CustomColumns) + ','
FROM ProductsCustomColumns
FOR xml path(''))
SELECT #cust_col = LEFT(#cust_col, Len(#cust_col) - 1)
SET #sql = 'SELECT *, ' + #cust_col + ' FROM Products WHERE UserId = 3 AND ProductId = 1'
EXEC (#sql)
In general it is a very bad idea to add custom data in additional columns of your main table. Just imagine 100 customers using this. All of them have differing table schemas and you wnat to write an update script for all of them?
It is a pain in the neck, if you have to deal with result sets where you don't know the structure in advance!
You have several choices:
Add one column of type XML. The advantage: The resultset is fix. You just need a customer specific rule, how to interpret the XML. You can solve this with an inline table valued function. Pass in the XML and get a derived table back. Call this with CROSS APPLY and you are out...
Add a new table with the customerID and Key-Value-Pairs
If the additional data is not completely different, add some of the columns to your main table as SPARSE columns

Querying a junction/link/bridge table, column data as header

I have a list of specialties (upwards of 20)
SpecialtyID Description
------------------------
1 Specialty1
2 Specialty2
3 Specialty3
I have a list of providers (upwards of 50)
ProviderID Name
------------------------
1 Tom
2 Maria
3 Pat
Each provider can have multiple specialties, each specialty can have multiple providers - so a many to many relationship.
I have a junction/link/bridge table called SpecialtyProvider and if I simply query the link table with the following query, I get the table below.
SELECT SpecialtyID, ProviderID FROM SpecialtyProvider
SpecialtyID ProviderID
------------------------
1 1
2 1
3 1
1 2
2 2
3 3
What I would like to do, is pull out the data formatted like so:
SpecialtyID ProviderID=1 ProviderID=2 ProviderID=3 ProviderID=x
-----------------------------------------------------------
1 true true NULL
2 true true NULL
3 true NULL true
Once I can format the data correctly, I'll be dumping this into an ASP ListView.
I am not quite sure how to proceed. I have read 100 posts about different variations of the PIVOT command, but where I don't have an aggregate function, I haven't been able to make any of the other examples/solutions/groupings make sense.
If you need to pivot without using an aggregate, you can usually just use MAX (you're essentially taking the MAX of a single value, which is just that same value).
select SpecialtyID, case when [1] is not null then 'true' end 'ProviderID=1',
case when [2] is not null then 'true' end 'ProviderID=2',
case when [3] is not null then 'true' end 'ProviderID=3'
from (
select s.SpecialtyID, s.Description, sp.ProviderID
from Specialty s
join SpecialtyProvider sp on sp.SpecialtyID = s.SpecialtyID
) x
pivot(
MAX(Description)
for ProviderID in ([1],[2],[3])
) pvt
SQL Fiddle
However, it's also possible to get the same results without using PIVOT at all:
select s.SpecialtyID,
Max(case when sp.ProviderID = 1 then 'true' end) 'ProviderID=1',
Max(case when sp.ProviderID = 2 then 'true' end) 'ProviderID=2',
Max(case when sp.ProviderID = 3 then 'true' end) 'ProviderID=3'
from Specialty s
join SpecialtyProvider sp on sp.SpecialtyID = s.SpecialtyID
group by s.SpecialtyID
I find this easier to read, and it will probably be faster as well.
SQL Fiddle
With all that said, you may want to reconsider your UI. Having a table 50 columns wide will be difficult for a user to process. It might make sense to filter the data so the user can only view specific portions of it. Also, if you're dealing with a variable number of providers, it may make sense to pull all the data up to the web server and process it in your ASP codebehind.
The following blog post introduces the concept of a dynamic pivot where you do not have to specify you columns so as to address the X factor for Providers. http://beyondrelational.com/modules/2/blogs/70/posts/10840/dynamic-pivot-in-sql-server-2005.aspx
I took it a bit further and also print out the generated SQL. Here is what I came up for to address your example above.
IF (OBJECT_ID(N'dynamic_pivot', N'P') IS NOT NULL)
DROP PROCEDURE dynamic_pivot
GO
CREATE PROCEDURE dynamic_pivot
(
#select VARCHAR(2000)
, #PivotCol VARCHAR(100)
, #Summaries VARCHAR(100)
, #GenerateScript BIT = 1
)
AS
BEGIN
SET NOCOUNT ON ;
DECLARE #pivot VARCHAR(MAX)
, #sql VARCHAR(MAX)
SELECT #select = REPLACE(#select, 'SELECT ',
'SELECT ' + #PivotCol + ' AS pivot_col, ')
CREATE TABLE #pivot_columns
(
pivot_column VARCHAR(100)
)
SELECT #sql = 'SELECT DISTINCT pivot_col FROM (' + #select + ') AS t'
INSERT INTO #pivot_columns
EXEC ( #sql
)
SELECT #pivot = COALESCE(#pivot + ',', '') + '[' + pivot_column + ']'
FROM #pivot_columns
SELECT #sql = '
SELECT *
FROM
(
' + #select + '
) AS t
PIVOT
(
' + #Summaries + ' for pivot_col in (' + #pivot + ')
) AS p'
PRINT #sql
EXEC(#sql)
END
GO
EXEC [dbo].[dynamic_pivot] #select = 'SELECT SpecialtyID, 1 AS hasSpecialty FROM SpecialtyProvider', -- varchar(2000)
#PivotCol = 'ProviderID', -- varchar(100)
#Summaries = 'COUNT(hasSpecialty)' -- varchar(100)
The resulting query that is displayed in your message window in SSMS is the following:
SELECT *
FROM
(
SELECT ProviderID AS pivot_col, SpecialtyID, 1 AS hasSpecialty FROM SpecialtyProvider
) AS t
PIVOT
(
COUNT(hasSpecialty) for pivot_col in ([1],[2],[3])
) AS p
You can modify this to give you the column names and values that are required.

transpose rows to columns in sql

I have problem in getting the desired output with the SQL query.
My sql data is as follows:
TOTAL Charge PAYMNET A B C D E MonthYear
------- ----------- ----------- --------- -------- ---------- ------- ------- ----------
661 157832.24 82967.80 700.00 10.70 58329.33 0.00 0.00 Oct-2013
612 95030.52 17824.28 850.00 66.10 53971.41 0.00 0.00 Nov-2013
584 90256.35 16732.91 700.00 66.10 52219.87 0.00 0.00 Dec-2013
511 72217.32 12336.12 285.00 53.17 42951.12 0.00 0.00 Jan-2014
I need the output as follows,
Data Jan-2013 Feb-2013 Mar-2013
TOTALCOUNT 761 647 671
Charge 126888 119995 151737.5
Payment 25705.4 26235.47 28704.41
A 1089.08 1020 745
B 2100.4 1947.25 1868.22
C 94246.55 84202.15 115673.7
D 0 0 0
E 0 0 0
I have seen the examples of pivot and unpivot, in pivot I don't get the column headers as row data, and in unpivot I didn't found an example where I can transpose multiple columns. I have another option to get this result in the code. But I want to know is it possible to get this kind of result in sql?
Edit
The result will give only for 3 or 4 months, not more than that.
Update : The first sample data is the actual data which I will get as a result of multiple joins and grouping on multiple tables, which I will store into a temp table. I tried to get the required result by modifying the query which is not possible because of the table structure. I managed to get the result as in the first sample data, but this is not what the client want to see!!! So I need to process the temp table data which will be only 3 to 4 rows into required output. The query to get the first result is select * from temp. The processing needs to be done on temp table result.
Update-2
I have tried the following query
declare #cols varchar(max)
select #cols = STUFF((select ', ' + MonthYear
from #tmp for xml path('')),1,1,'')
declare #query varchar(max)
set #query =
'select ''TOTAL'' as Data,' +#cols+' from
(select MonthYear,TOTALCLAIMS from #tmp)st
pivot
(
MAX(TOTAL) for MonthYear in (' + #cols + ')
)pt;'
Which gave me the first row correctly!!! But I tried to use union as
set #query =
'select ''TOTAL'' as Data,' +#cols+' from
(select MonthYear,TOTALCLAIMS from #tmp)st
pivot
(
MAX(TOTAL) for MonthYear in (' + #cols + ')
)pt;
union
select ''CHARGES'' as Data,' +#cols+' from
(select MonthYear,TOTALCLAIMS from #tmp)st
pivot
(
MAX(CHARGES) for MonthYear in (' + #cols + ')
)pt;'
Which gives an error as incorrect syntax near union. Any one know how to union pivot results? Or is there any better way to do this?
Thank You.
I have tried this code. Please check and let me know if it works
I know that it doesnt look so good. Also not sure how it will be performance wise.
--Can have more columns like A,B,...
DECLARE #tbl TABLE
(
TOTAL INT,
CHARGE FLOAT,
PAYMENT FLOAT,
MONTHYEAR VARCHAR(50)
)
--Test data
INSERT INTO #tbl SELECT 661, 157832.24, 82967.80, 'Oct2013'
INSERT INTO #tbl SELECT 612, 95030.52, 17824.28, 'Nov2013'
INSERT INTO #tbl SELECT 584 ,90256.35, 16732.91, 'Dec2013'
--Can be a physical table
CREATE TABLE #FinalTbl
(
DATA VARCHAR(100)
)
--inserted hardcode records in data column. To add it dynamically you would need to loop through information_schema.columns
--SELECT *
--FROM information_schema.columns
--WHERE table_name = 'tbl_name'
INSERT INTO #FinalTbl
VALUES ('TOTAL')
INSERT INTO #FinalTbl
VALUES ('CHARGE')
INSERT INTO #FinalTbl
VALUES ('PAYMENT')
DECLARE #StartCount INT, #TotalCount INT, #Query VARCHAR(5000), #TOTAL INT,#CHARGE FLOAT,#PAYMENT FLOAT,#MONTHYEAR VARCHAR(50)
SELECT #TotalCount = COUNT(*) FROM #tbl;
SET #StartCount = 1;
WHILE(#StartCount <= #TotalCount)
BEGIN
SELECT #TOTAL = TOTAL,
#CHARGE = CHARGE,
#PAYMENT = PAYMENT,
#MONTHYEAR = MONTHYEAR
FROM
(SELECT ROW_NUMBER() over(ORDER BY MONTHYEAR) AS ROWNUM, * FROM #tbl) as tbl
WHERE ROWNUM = #StartCount
SELECT #Query = 'ALTER TABLE #FinalTbl ADD ' + #MONTHYEAR + ' VARCHAR(1000)'
EXEC (#Query)
SELECT #Query = 'UPDATE #FinalTbl SET ' + #MONTHYEAR + ' = ''' + CONVERT(VARCHAR(50), #TOTAL) + ''' WHERE DATA = ''TOTAL'''
EXEC (#Query)
SELECT #Query = 'UPDATE #FinalTbl SET ' + #MONTHYEAR + ' = ''' + CONVERT(VARCHAR(50), #CHARGE) + ''' WHERE DATA = ''CHARGE'''
EXEC (#Query)
SELECT #Query = 'UPDATE #FinalTbl SET ' + #MONTHYEAR + ' = ''' + CONVERT(VARCHAR(50), #PAYMENT) + ''' WHERE DATA = ''PAYMENT'''
EXEC (#Query)
SELECT #StartCount = #StartCount + 1
END
SELECT * FROM #FinalTbl
DROP TABLE #FinalTbl
Hope this helps
I would imagine the reason you are only getting 3 or 4 months is because you don't have data for the missing months? If you want to display columns for missing months you will need to either:
Create a Table datatype with all the months you want to display
and left join the remainder of the tables to it in your query. You
could then use the PIVOT function as normal.
If you know how many columns up front i.e. one for each month in a particular year and it won't change, you can simply use CASE
Statements (one for each month) to transpose the data without the
PIVOT operator.
I can provide examples if needed.
Select Month(Mdate)md,'A' AS Col,sum(A) as a from Product group by Month(MDate)
union all
Select Month(Mdate)md,'B',sum(b) as a from Product group by Month(MDate)
union all
Select Month(Mdate)md,'C',sum(c) as a from Product group by Month(MDate)
union all
Select Month(Mdate)md,'D',Count(A) as a from Product group by Month(MDate)
Try Pivot with the above query you may to get required result....