How to use dynamically pivot to generate timetable - sql-server

I want to generate a timetable and I have these columns:
Time Itinerary ID
06:35 3579 87069
07:15 3031 63722
07:15 3031 68218
16:30 3031 82745
16:30 3031 88308
21:00 3031 72212
21:00 3031 76241
06:55 3576 87069
07:25 3333 63722
07:25 3333 68218
16:40 3333 82745
And I want to get this:
3579 3031 3576 3333
87069 06:35 06:55
63722 07:15
68218 07:15
.
.
.
The number of Itineraries are variable and i can get this information from one table.

Full working example of dynamic PIVOT:
CREATE TABLE #DataSource
(
[Time] TIME
,[Itinerary] INT
,[ID] INT
);
INSERT INTO #DataSource ([Time], [Itinerary], [ID])
VALUES ('06:35', '3579', '87069')
,('07:15', '3031', '63722')
,('07:15', '3031', '68218')
,('16:30', '3031', '82745')
,('16:30', '3031', '88308')
,('21:00', '3031', '72212')
,('21:00', '3031', '76241')
,('06:55', '3576', '87069')
,('07:25', '3333', '63722')
,('07:25', '3333', '68218')
,('16:40', '3333', '82745');
DECLARE #DynammicTSQLStatement NVARCHAR(MAX)
,#DynamicPIVOTColumns NVARCHAR(MAX);
SET #DynamicPIVOTColumns = STUFF
(
(
SELECT ',[' + CAST([Itinerary] AS VARCHAR(12)) + ']'
FROM #DataSource
GROUP BY [Itinerary]
ORDER BY [Itinerary]
FOR XML PATH('') ,TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,1
,''
);
SET #DynammicTSQLStatement = N'
SELECT *
FROM #DataSource
PIVOT
(
MAX([Time]) FOR [Itinerary] IN (' + #DynamicPIVOTColumns + ')
) PVT';
EXEC sp_executesql #DynammicTSQLStatement;
DROP TABLE #DataSource;

Related

Concatenate comma separated strings using STUFF

I want to concatenate comma-separated string. I have a query where I am using the function to get the staff.
Currently, I am using [dbo].fn_fullname(A.REFNO) as Staff to get the staff but I want to include some conditions if the count of cast(S.SCH_NO as varchar) as ReferenceIdentifier is greater than 1 then concatenate the value. But not sure how it can be achieved inside the view itself.
Here I am trying to use STUFF to concatenate.
Here is the query:
Alter View vw_TestDB
AS
select
NEWID() as UniqueKey,
P.ID as Number,
cast(S.SCH_NO as varchar) as ReferenceIdentifier,
cast(S.START_D as datetime2) as StartDateTime,
staff = STUFF((
SELECT ',' + [dbo].fn_fullname(A.REFNO)
FROM [dbo].[vw_TESTDB]
FOR XML PATH('')
), 1, 1, '')
FROM [dbo].[vw_TestDB]
group by ReferenceIdentifier
having count(ReferenceIdentifier)>1,
[dbo].fn_fullname(A.REFNO) as Staff,
from [dbo].V_SCHEDULES S WITH (NOLOCK)
inner join [dbo].V_PAT P WITH (NOLOCK) on P.PAT_REFNO = S.PAT_REFNO
Here the function:
ALTER FUNCTION [dbo].[fn_fullname]
(
#refno as numeric(10, 0)
)
RETURNS varchar(100)
AS
BEGIN
DECLARE #name as varchar(100)
SELECT #name = Stuff(Coalesce(' ' +
CASE
WHEN proca.TITLE_REFNO = 3104
THEN NULL
ELSE
NullIf(dbo.fn_rfval(proca.TITLE_REFNO), '')
END,
'') +
Coalesce(' ' + proca.forename, '') +
Coalesce(' ' + proca.surname, ''),
1,
1,
'')
FROM dbo.v_carers_active proca (nolock)
WHERE refno = #refno
return #name
END
GO
Here are sample data
UniqueKey
Number
ReferenceIdentifier
StartDateTime
staff
70DB83D1-2900-4CF1-9CC4-CA6948AC0E91
A4286
2182823
2015-03-26 08:00:00.0000000
Ms S Taylor
310745CB-4724-4724-A5F0-7D9088317E58
A4286
2182823
2015-03-26 08:00:00.0000000
Ms D Kirkpatrick
CA6DDB25-AADD-4FC1-ABAA-2AF84016E6E5
A4286
2182834
2015-03-19 08:00:00.0000000
Ms D Kirkpatrick
6A3C0A3B-EAA3-4523-B4FD-2882E2C02B4A
A4286
2182844
2015-03-30 08:00:00.0000000
Mrs Nel McKinnon
6399662A-EC4D-4993-8D4F-0BC396D12C2C
A4286
2182844
2015-03-30 08:00:00.0000000
Ms Deb Kirkpatrick
Expected output
UniqueKey
Number
ReferenceIdentifier
StartDateTime
staff
70DB83D1-2900-4CF1-9CC4-CA6948AC0E91
A4286
2182823
2015-03-26 08:00:00.0000000
Ms S Taylor,Ms D Kirkpatrick
CA6DDB25-AADD-4FC1-ABAA-2AF84016E6E5
A4286
2182834
2015-03-19 08:00:00.0000000
Ms D Kirkpatrick
6A3C0A3B-EAA3-4523-B4FD-2882E2C02B4A
A4286
2182844
2015-03-30 08:00:00.0000000
Mrs Nel McKinnon,Ms Deb Kirkpatrick
Not quite understand what you wanted. Based on the sample data and expected output, it seems like you wanted
SELECT t.[Number], t.[ReferenceIdentifier], t.[StartDatetime],
STUFF (
(SELECT ',' + [dbo].fn_fullname(x.REFNO)
FROM yourtable AS x
WHERE x.[Number] = t.[Number]
AND x.[ReferenceIdentifier] = t.[ReferenceIdentifier]
AND x.[StartDatetime] = t.[StartDatetime]
FOR XML PATH('')),
1, 1, '') AS Staff
FROM yourtable t
GROUP BY t.[Number], t.[ReferenceIdentifier], t.[StartDatetime]
HAVING COUNT(*) > 1

Select data from multiple tables with same column names and structure using sql

I am get data from a third party database to generate certain reports. The issue is that it keeps on generating a new table every month to insert the same record in same columns in the following manner:
For December table : Data_12_2019
For January table : Data_1_2020
For February table : Data_2_2020
For March table : Data_3_2020 and so on
and table data is as following:
UserId DLogId LogDate
1461 1799 2020-01-06 09:07:51.000
1462 1803 2020-01-07 09:29:39.000
1463 1806 2020-01-07 11:43:11.000
1464 1807 2020-01-09 09:16:47.000
1457 1819 2020-01-10 09:00:56.000
table2
UserId DLogId LogDate
1466 1853 2020-02-03 09:11:54.000
1468 1831 2020-02-04 09:17:09.000
1470 1833 2020-02-5 09:01:06.000
and need output in a single table in following manner:
UserId DLogId LogDate
1461 1799 2020-01-06 09:07:51.000
1462 1803 2020-01-07 09:29:39.000
1463 1806 2020-01-07 11:43:11.000
1464 1807 2020-01-09 09:16:47.000
1457 1819 2020-01-10 09:00:56.000
1466 1853 2020-02-03 09:11:54.000
1468 1831 2020-02-04 09:17:09.000
1470 1833 2020-02-5 09:01:06.000
I want to get data placed in above tables and tables that will be generated in future also.
I am seeking a help about how to do it.
You can achieve this using dynamic query. If your table structure is same, you can try like following.
DECLARE #query AS NVARCHAR(max) = Stuff((SELECT DISTINCT ' ' + 'SELECT * FROM ' + Quotename(name) + ' UNION'
FROM
(
SELECT
[name]
FROM
sys.sysobjects
WHERE
[xtype] = 'U'
and NAME LIKE 'Data_[0-9][0-9]_[0-9][0-9][0-9][0-9]'
)t
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, '');
SET #query= substring(#query,0,len(#query)-5)
exec(#query)
Note: Better replace * with the column names you want.
To get all the tables you can use sysobject and filter out based on table names like
SELECT [name]
FROM sys.sysobjects
WHERE [xtype] = 'U'
AND NAME LIKE 'Data_[0-9][0-9]_[0-9][0-9][0-9][0-9]'
And build a dynamic query using UNION.
PREPARE stmt1 FROM ' SELECT GROUP_CONCAT('SELECT * FROM ',TABLE_NAME,' UNION ')
FROM information_schema.tables
WHERE table_schema =? AND table_name LIKE 'Data_%'';
SET #a = 'MyDb';
EXECUTE stmt1 USING #a;

Struggling with a dynamic pivot on multiple columns with one being concatenated

I have a table with data like so:
Employee PRDate Type Code Amount Subject Eligible
1234 1/1/2015 D 1 100.00 100.00 0.00
1234 1/1/2015 D 2 200.00 0.00 0.00
5678 1/1/2015 D 1 500.00 40.00 500.00
1234 1/1/2015 E 1 300.00 30.00 300.00
5678 1/1/2015 E 1 700.00 700.00 500.00
1234 1/1/2015 E 2 400.00 200.00 0.00
1234 1/8/2015 L 55 40.00 40.00 40.00
And I need for the data to be displayed like this:
Employee PRDate D1Amt D1Subj D1Elig D2Amt D2Subj D2Elig E1Amt E1Subj E1Elig E2Amt E2Subj E2Elig L55Amt L55Subj L55Elig
1234 1/1/2015 100.00 100.00 0.00 200.00 0.00 0.00 300.00 30.00 300.00 400.00 200.00 0.00 40.00 40.00 40.00
4678 1/1/2015 500.00 40.00 500.00 700.00 700.00 500.00
I can pivot on one column but when I try combining the Type and Code columns to get the one I get conversion errors (Type is a varchar and code is a tinyint). I'm not sure how to get to the desired results other than dynamic pivot. Can the desired results be achieved?
I've gotten this far but I can't figure out how to combine the type, code and each money columns (amount, subject and eligible) to get the data under the correct columns.
IF EXISTS (
SELECT *
FROM sys.tables
WHERE name LIKE '#temp285865%')
DROP TABLE #temp285865;
Create table dbo.#temp285865
(
EDLCodetemp varchar(10)
);
INSERT INTO #temp285865
(
[EDLCodetemp]
)
SELECT DISTINCT EDLCode
FROM #results
ORDER BY EDLCode;
-- Building a comma separated list of EDLCodes in #edltemp
DECLARE #cols varchar(1000);
SELECT #cols = COALESCE(#cols + ',[' + [EDLCodetemp] + ']', '[' + [EDLCodetemp] + ']')
FROM #temp285865;
-- Building the query appending columns
DECLARE #query varchar(4000);
SET #query =
'SELECT [CoName],
[PRCo],
[PRGroup],
[PREndDate],
[PaySeq],
[EDLType],
[Hours],
[SubjectAmt],
[EligibleAmt],
[PaidMth],
[LastName],
[FirstName],
[UseOver],
[OverAmt],
[Amount],
[PRGRDescrip],
[LimitPeriod],
[LimitMth],
[PREHEmployee],
[SortName],
[PaybackAmt],
[PaybackOverAmt],
[PaybackOverYN],
[PRDTEmployee],
[TrueEarns], '
+ #cols + ' FROM
(
SELECT [CoName],
[PRCo],
[PRGroup],
[PREndDate],
[PaySeq],
[EDLType],
[Hours],
[SubjectAmt],
[EligibleAmt],
[PaidMth],
[LastName],
[FirstName],
[PRDLDescrip],
[PRECDescrip],
[UseOver],
[OverAmt],
[Amount],
[PRGRDescrip],
[LimitPeriod],
[LimitMth],
[PREHEmployee],
[SortName],
[PaybackAmt],
[PaybackOverAmt],
[PaybackOverYN],
[PRDTEmployee],
[TrueEarns],
[EDLCode]
FROM #results
) p
PIVOT (
MAX(EDLCode)
FOR [EDLCode] IN (' + #cols + ')
)
as pvt';
EXEC(#query);
DROP TABLE #temp285865;
The following PIVOT with dynamic SQL would give you the result you want, based on the input data you provided (I changed the PRDate in the last row though).
The first statement builds an intermediate table #bt with the column names you want and the associated value. Then the column names are built in #cols for the dynamic SQL statement. Finally the intermediate table #bt is pivoted with a dynamic SQL statement using the #cols to pivot.
SET NOCOUNT ON;
CREATE TABLE #t(
Employee INT,
PRDate DATETIME,
Type CHAR(1),
Code TINYINT,
Amount DECIMAL(28,2),
Subject DECIMAL(28,2),
Eligible DECIMAL(28,2)
);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','D',1,100.00,100.00,0.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','D',2,200.00,0.00,0.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(5678,'2015-01-01','D',1,500.00,40.00,500.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','E',1,300.00,30.00,300.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(5678,'2015-01-01','E',1,700.00,700.00,500.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','E',2,400.00,200.00,0.00);
INSERT INTO #t(Employee,PRDate,Type,Code,Amount,Subject,Eligible)VALUES(1234,'2015-01-01','L',55,40.00,40.00,40.00);
SELECT
Employee,
PRDate,
Type+CAST(Code AS VARCHAR(3))+ca.name AS colname,
ca.val
INTO
#bt
FROM
#t
CROSS APPLY(
SELECT Amount AS val,'Amt' AS name
UNION ALL
SELECT Subject AS val,'Subj' AS name
UNION ALL
SELECT Eligible AS val,'Elig' AS name
) AS ca;
/* If you need to SUM for all dates, instead use this statement to create #bt
SELECT
Employee,
Type+CAST(Code AS VARCHAR(3))+ca.name AS colname,
ca.val
INTO
#bt
FROM
(
SELECT
Employee,
Type,
Code,
SUM(Amount) AS Amount,
SUM(Subject) AS Subject,
SUM(Eligible) AS Eligible
FROM
#t
GROUP BY
Employee,
Type,
Code
) AS t
CROSS APPLY(
SELECT Amount AS val,'Amt' AS name
UNION ALL
SELECT Subject AS val,'Subj' AS name
UNION ALL
SELECT Eligible AS val,'Elig' AS name
) AS ca;
*/
DECLARE #cols VARCHAR(8000);
SET #cols=STUFF(
(SELECT DISTINCT
',['+colname+']'
FROM
#bt
FOR XML PATH('')),
1,
1,
''
);
DECLARE #sql VARCHAR(MAX);
SET #sql='
SELECT
*
FROM
#bt
PIVOT(
MAX(val)
FOR colname IN ('+#cols+')
) AS piv
';
EXEC (#sql);
DROP TABLE #bt;
DROP TABLE #t;
The result is the following:
Employee PRDate D1Amt D1Elig D1Subj D2Amt D2Elig D2Subj E1Amt E1Elig E1Subj E2Amt E2Elig E2Subj L55Amt L55Elig L55Subj
1234 2015-01-01 100.00 0.00 100.00 200.00 0.00 0.00 300.00 300.00 30.00 400.00 0.00 200.00 40.00 40.00 40.00
5678 2015-01-01 500.00 500.00 40.00 NULL NULL NULL 700.00 500.00 700.00 NULL NULL NULL NULL NULL NULL

Create query with dynamic columns from different tables

I'm trying to create a query with dynamic columns, based on data from three tables.
This is the database structure:
STUDENT
studentID int,
studentNumber int,
studentName nvarchar(100).
EXAM:
examID int,
examName varchar(100),
examenDate datetime,
EXAM_REGISTRATION:
studentID int,
examID int,
A record is added to the EXAM_REGISTRATION table when a student has registered for an exam.
What I'm trying to get is a list of all the exams and all the students in a pivot table to see which students have registered for which exams, like this:
Quite frankly I don't know where to start.
I can query everything individually and put it all together but how can I combine it into one query?
I've been researching pivot tables, but every example seems to query only from one table and uses numbers and functions like MIN, AVG etc.
Can someone help me along?
ok lets go
some data to play with
create table #student
(studentID int, studentNumber int, studentName nvarchar(100))
create table #exam
(examID int, examName nvarchar(100), examDate datetime)
create table #examReg
(studentID int, examID int)
insert into #student
values (1, 787878, 'pierwszy')
,(2, 89898, 'drugi')
,(3, 343434, 'trzeci')
,(4, 121212, 'czwarty')
insert into #exam
values (1, 'exPierwszy', GETDATE())
,(2, 'exDrugi', GETDATE())
,(3, 'exTrzeci', GETDATE())
insert into #examReg
values (1,2),(1,3)
, (2,2),(2,3)
,(3,1),(3,2)
,(4,1),(4,2),(4,3)
and now the main part, and explanation
first of all you have to get pivot query
select examName, examDate , min([1]) , min([2]), min([3]) ,min([4])--studentID as studentID, examDate --,studentNumber
from
(select a.studentID , studentNumber, examDate, examName
from #student a
join #examReg b on a.studentID = b.studentID
join #exam c on c.examID = b.examID ) as m
pivot
(min(studentNumber) FOR studentID in ([1],[2],[3],[4])) as t
group by examName, examDate
as you have it , just change it select statement and studentID list in pivot declaration, you have to generate those parts dynamicly , so we just copy previously written query and replace columns with our token
declare #sqlTemplate nvarchar(max) =
'select examName, examDate ##sqlColumnList##
from
(select a.studentID , studentNumber, examDate, examName
from #student a
join #examReg b on a.studentID = b.studentID
join #exam c on c.examID = b.examID ) as m
pivot
(min(studentNumber) FOR studentID in (##sqlStudentIDList##)) as t
group by examName, examDate
'
after that you generate column list and studentID list by concatenting strings in tsql
declare #sqlColumnList nvarchar(max) = ''
select #sqlColumnList += ',min([' + cast(studentID as nvarchar(10)) + ']) as [' + studentName +'(' + cast(studentNumber as nvarchar(10)) + ')]'
from #student
declare #sqlStudentIDList nvarchar(max) = ''
select #sqlStudentIDList += '[' + CAST(studentID as nvarchar(10)) + '],'
from #student
set #sqlStudentIDList = SUBSTRING(#sqlStudentIDList, 0, LEN(#sqlStudentIDList))
select #sqlStudentIDList
once you have it , all you have to do is to replace tokens in previous template
set #sqlTemplate = REPLACE(#sqlTemplate, '##sqlColumnList##', #sqlColumnList)
set #sqlTemplate = REPLACE(#sqlTemplate, '##sqlStudentIDList##', #sqlStudentIDList)
select #sqlTemplate
exec sp_executesql #sqlTemplate
and thats it
if you want to read more about pivot go for msdn
if you want to read about dynamic go for this link
edit: to adjust the query for the question from comment you would have to change #sqlColumnList like that
select #sqlColumnList += ',min(' + QUOTENAME(studentID) + ') as Student' + CAST(studentID as nvarchar(10)) + '_REG,
'''+ studentName + ''' as Student' + cast(studentID as nvarchar(10)) + '_NAME,
'+ cast(studentID as nvarchar(10)) + ' as Student' + cast(studentID as nvarchar(10)) + '_ID'
from #student
This is a pivot of the data. I would perform this slightly different than the other answer. If you know all of the values, then you can hard-code the values.
A static version will be:
select examname,
examendate,
IsNull([Smith, John (14323)], 'false') [Smith, John (14323)],
IsNull([Craft, Peter (14334)], 'false') [Craft, Peter (14334)],
IsNull([Davis, Alan (13432)], 'false') [Davis, Alan (13432)],
IsNull([Newman, Ted (133123)], 'false') [Newman, Ted (133123)]
from
(
select e.examname,
e.examenDate,
s.studentName + ' ('+cast(s.studentnumber as varchar(50))+')' studentNameNum,
'true ' as Flag
from exam e
left join exam_registration er
on e.examid = er.examid
right join student s
on er.studentid = s.studentid
) src
pivot
(
max(flag)
for studentNameNum in ([Smith, John (14323)], [Craft, Peter (14334)],
[Davis, Alan (13432)], [Newman, Ted (133123)])
) piv
See SQL Fiddle with Demo
If your values are unknown then the query will be:
DECLARE #cols AS NVARCHAR(MAX),
#colsNull AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(s.studentName + ' ('+cast(s.studentnumber as varchar(50))+')')
from student s
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #colsNull = STUFF((SELECT distinct ',IsNull(' + QUOTENAME(s.studentName + ' ('+cast(s.studentnumber as varchar(50))+')')+', ''false'')'+' as '+QUOTENAME(s.studentName+' ('+cast(s.studentnumber as varchar(50))+')')
from student s
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT examname,
examenDate,' + #colsNull + ' from
(
select e.examname,
e.examenDate,
s.studentName + '' (''+cast(s.studentnumber as varchar(50))+'')'' studentNameNum,
''true '' as Flag
from exam e
left join exam_registration er
on e.examid = er.examid
right join student s
on er.studentid = s.studentid
) x
pivot
(
max(flag)
for studentNameNum in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle with Demo
The result will be:
| EXAMNAME | EXAMENDATE | CRAFT, PETER (14334) | DAVIS, ALAN (13432) | NEWMAN, TED (133123) | SMITH, JOHN (14323) |
----------------------------------------------------------------------------------------------------------------------------
| Exam 1 | 2013-01-01 12:00:00 | false | false | true | false |
| Exam 2 | 2013-01-01 14:00:00 | true | false | false | true |
| Exam 3 | 2013-01-02 12:00:00 | true | true | false | false |
| Exam 4 | 2013-01-02 14:00:00 | false | false | true | false |
| Exam 5 | 2013-01-03 12:00:00 | false | false | false | true |

How can I write a Pivot table to display records for each year as columns?

I'm pretty sure I need a pivot to do this but can't quite figure it out. (sql newb)
I have data like this:
ID CompanyID Year Revenue Expenses
1 0003 2011 12000 4000
2 0003 2010 9000 6000
3 0003 2009 7000 9000
4 0010 2011 134300 34000
5 0010 2010 43000 46000
6 0010 2009 73000 39000
Can I use a Pivot to display this table like this:
CompanyID 2011-Revenue 2010-Revenue 2009-Revenue 2011-Expenses 2010-Expenses 2009-Expenses
0003 12000 9000 7000 4000 6000 9000
0010 134300 43000 73000 34000 46000 39000
Here is what I have so far...
SELECT P1.*
FROM (SELECT [CompanyID]
,CASE P.[Year] WHEN 2011 THEN P.[Revenue] ELSE NULL END AS '2011-Revenue'
,CASE P.[Year] WHEN 2010 THEN P.[Revenue] ELSE NULL END AS '2010-Revenue'
FROM tblRecords P WHERE P.[CompanyID] = #companyID GROUP BY CompanyID, [Year], [Revenue]) AS P1
Which is returning:
CompanyID 2011-Revenue 2010-Revenue
0003 12000 NULL
0003 NULL 9000
Few problems with my results...
The there is two records for CompanyID 0003 I'd like it to group into one record
I can only choose 1 company at a time, I need to choose multiple. I tried
FROM tblRecords P
WHERE P.[CompanyID] IN (#CompanyIDs)
GROUP BY CompanyID, [Year], [Revenue]) AS P1
Where #CompanyIDs is a string like '0003, 0010' - It didn't fail but the result was just an empty table with the headers and no data..
Any help would be appreciated.. or let me know if I'm misunderstanding pivot?
Thanks a lot!
Thomas
EDIT: Using Microsoft SQL Server Management Studio 2005 Express
UPDATE 2: I've figured out joining tables for more details however I still need to be able to pass in the the CompanyIDs as a comma delimited string.. any help on that would be appreciated.
vvvvvvvv I'VE FIGURED OUT BELOW THIS (will post once all is working) vvvvvvv
UPDATE: It looks like what Ruben has proposed is going to work however I've just determined I need a bit more functionality to this... Can I join this with another table to have the headers
CompanyID CompanyName CompanyAddress 2011-Revenue 2010-Revenue
Where CompanyName and CompanyAddress come from another table (tblCompanyDetails)
I've tried using:
SELECT *
FROM
(
SELECT CompanyID, tblCompanyDetails.CompanyName, tblCompanyDetails.CompanyAddress, CAST(YEAR AS varchar) + ' - Revenue' Type,
Revenue Value FROM tblRecords
FROM tblRecords INNER JOIN tblCompanyDetails ON tblRecords.CompanyID = tblCompanyDetails.CompanyID
UNION ALL
SELECT CompanyID, tblCompanyDetails.CompanyName, tblCompanyDetails.CompanyAddress, CAST(YEAR AS varchar) + ' - Expenses' Type,
Expenses Value FROM tblRecords
FROM tblRecords INNER JOIN tblCompanyDetails ON tblRecords.CompanyID = tblCompanyDetails.CompanyID
) src
PIVOT
(
SUM(Value) for [Type] in
([2011 - Revenue], [2010 - Revenue], [2009 - Revenue],
[2011 - Expenses], [2010 - Expenses], [2009 - Expenses]
)
) pvt
WHERE CompanyID = #CompanyID
I get the error:
Msg 1038, Level 15, State 4, Procedure spCompare, Line 10
An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Add a name or single space as the alias name.
Try this:
DECLARE #CompanyIDs XML
DECLARE #Records TABLE
(
ID int,
CompanyID char(4),
Year int,
Revenue decimal,
Expenses decimal
)
DECLARE #CompanyDetails TABLE
(
CompanyID char(4),
Name varchar(50),
Address varchar(50)
)
SET #CompanyIDs = '
<filter>
<CompanyID>0003</CompanyID>
<CompanyID>0010</CompanyID>
</filter>'
INSERT INTO #Records
(ID, CompanyID, Year, Revenue, Expenses)VALUES
(1, '0003', 2011, 12000 , 4000 ),
(2, '0003', 2010, 9000 , 6000 ),
(3, '0003', 2009, 7000 , 9000 ),
(4, '0010', 2011, 134300, 34000),
(5, '0010', 2010, 43000 , 46000),
(6, '0010', 2009, 73000 , 39000)
INSERT INTO #CompanyDetails
(CompanyID, Name, Address) VALUES
('0003', 'Company A', 'A Street'),
('0010', 'Company B', 'B Street')
SELECT *
FROM
(
SELECT CompanyID, CAST(YEAR AS varchar) + ' - Revenue' Type,
Revenue Value FROM #Records
UNION ALL
SELECT CompanyID, CAST(YEAR AS varchar) + ' - Expenses' Type,
Expenses Value FROM #Records
) src
PIVOT
(
SUM(Value) for [Type] in
([2011 - Revenue], [2010 - Revenue], [2009 - Revenue],
[2011 - Expenses], [2010 - Expenses], [2009 - Expenses]
)
) pvt
JOIN #CompanyDetails Details
ON Details.CompanyId = pvt.CompanyID
WHERE pvt.CompanyID IN
(
SELECT T.C.value('.', 'char(4)')
FROM #CompanyIDs.nodes('/filter/CompanyID') T(C)
)
You need to send your company filter as XML and use that subselect to break your data as required for pivot operations. For JOIN operations, just use pvt output

Resources