Update data based on parameter with operator from another table - sql

I have 2 tables with sample data below:
tblSale
PartCode PartGroup SaleQty
a FM 600
b MM 202
c SM 10
d NM 0
tblCondition
PartGroup Condition
FM >500
MM >=200
SM >=1
NM 0
in SQL Server stored procedure i want to update PartGroup in tblSale by PartGroup in tblCondition based on sum(SaleQty) and compare with Condition.
Any help please.
UPDATE:
Example:
PartCode 'A' is has PartGroup='FM' and SaleQty=500.
if SaleQty=400 then update PartGroup='MM' based on Condition in tblCondition.
UPDATE tblSale
SET tblSale.PartGroup=tblCondition.PartGroup
WHERE SUM(tblSale.Sale) ??? tblCondition.Condition

I don't think you will be able to do this without dynamic code.
For my solution you will need make some changes/notes:
change PartGroup NM condition 0 to =0
make sure that tblCondition table conditions are inserted from biggest (500) to lowest (0)
First what I do is create CASE for every row from tblCondition table.
Then I SUM data to temp table by PartCode (I split PartCode 'c' to 2 rows for testing)
And for the last, create dynamic code, which will update data
/*
CREATE TABLE #tblSale ( PartCode VARCHAR(10), PartGroup VARCHAR(10), SaleQty INT)
INSERT INTO #tblSale SELECT 'a', 'FM', 600
INSERT INTO #tblSale SELECT 'b', 'MM', 202
INSERT INTO #tblSale SELECT 'c', 'SM', 5
INSERT INTO #tblSale SELECT 'd', 'NM', 0
INSERT INTO #tblSale SELECT 'c', 'SM', 5
CREATE TABLE #tblCondition ( PartGroup VARCHAR(10), Condition VARCHAR(10))
INSERT INTO #tblCondition SELECT 'FM', '>500'
INSERT INTO #tblCondition SELECT 'MM', '>=200'
INSERT INTO #tblCondition SELECT 'SM', '>=1'
INSERT INTO #tblCondition SELECT 'NM', '=0'
*/
--CREATE CASES
DECLARE #CaseStr NVARCHAR(1000) = 'CASE '
SELECT #CaseStr = #CaseStr + '
WHEN SaleSUM ' + Condition + ' THEN '''+ PartGroup + ''' '
FROM #tblCondition
SET #CaseStr = #CaseStr + ' END'
-- SUM data by PartCode
SELECT PartCode, SUM(SaleQty) AS SaleSUM
INTO #tblSaleSUM
FROM #tblSale
GROUP BY PartCode
-- Create dynamic code for update
DECLARE #query NVARCHAR(MAX)
SET #query = N'
UPDATE S
SET S.PartGroup = SS.PartGroup
FROM #tblSale AS S
INNER JOIN
(
SELECT PartCode, ' + #CaseStr + ' AS PartGroup
FROM #tblSaleSUM
) AS SS
ON SS.PartCode = S.PartCode
'
EXEC sp_executesql #query

Use this
update ts set partGroup = something
from tblSale ts
inner join tblCondition tc
on tc.PartGroup=ts.PartGroup
inner join (Select PartGroup, sum(SaleQty) as SumSaleQty
from tblSale
group by PartGroup) as sums
on sums.PartGroup = tc.PartGroup
and sums.SumSaleQty >= tc.Condition

Related

SQL Server map rows with columns of different table

I am trying to create a result based on row and column value mapping. This is an example
First table (#column_table) has colunm_id and column_name.
Second table #column_value has values for the rows in First Table.
I want to create a dataset that looks like below:
How do I achieve that?
Here are the temp tables for data setup.
create table #column_table (column_id int, column_name varchar(50) )
insert into #column_table
values
(1, 'FirstName'),
(2, 'LastName'),
(3, 'Address'),
(4, 'Phone')
create table #column_value(FirstName varchar(50), LastName varchar(50), Phone varchar(50),)
insert into #column_value
values
('John','Smith','1234567')
select * from #column_table
select * from #column_value
UNPIVOT would be more performant, but if you need a more dynamic approach without actually using Dynamic SQL
Example
Select D.Column_ID
,Column_Value = C.Value
From #column_value A
Cross Apply (values (convert(xml,(Select A.* For XML Raw)))) B(XMLData)
Cross Apply (
Select Item = xAttr.value('local-name(.)', 'varchar(100)')
,Value = xAttr.value('.','varchar(max)')
From XMLData.nodes('//#*') xNode(xAttr)
) C
Join #column_table D on C.Item=D.Column_Name
Returns
Column_ID Column_Value
1 John
2 Smith
4 1234567
You can achieve this using UnPivot which is more performant, but as #JohnCappelleti mentioned you need to implement a Dynamic SQL logic:
Side Notes: i used like '#column_value%' not = '#column_value' because the example is handling a temp table. Also, You should replace #column_value and #column_table by corresponding tables names. Also, i used tempdb.information_schema because temp tables are stored in tempdb database.
--Create Tables and insert values
create table #column_table (column_id int, column_name varchar(50) )
insert into #column_table
values
(1, 'FirstName'),
(2, 'LastName'),
(3, 'Address'),
(4, 'Phone')
create table #column_value(FirstName varchar(50), LastName varchar(50), Phone varchar(50),)
insert into #column_value
values
('John','Smith','1234567')
select * from #column_table
select * from #column_value
--Get columns found in both tables
SELECT t2.column_id,t2.column_name
INTO #tblTemp
from tempdb.information_schema.columns t1
inner join #column_table t2 on t1.COLUMN_NAME = t2.column_name
where t1.table_name like '#column_value%'
--Building Dynamic Query
DECLARE #strQuery VARCHAR(4000) = 'SELECT * FROM (SELECT '
DECLARE #strUnPivot as varchar(max) = ' UNPIVOT ([Value] for [Column_ID] IN ('
SELECT #strUnPivot = ISNULL(#strUnPivot,'') + '[' + CAST(column_id as varchar(10)) + '] ,' From #tblTemp
SELECT #strQuery = #strQuery + '[' + column_name + '] AS "' + CAST(column_id as varchar(10)) + '",' From #tblTemp
SELECT #strQuery = SUBSTRING(#strQuery,1,LEN(#strQuery) - 1) + ' FROM #column_value) AS p ' + SUBSTRING(#strUnPivot,1,LEN(#strUnPivot) - 1) + ')) AS unpvt '
--Execute Query
EXEC(#strQuery)
Result
References
How to convert a column header and its value into row in sql?
Select non-empty columns using SQL Server
With CASE and a cross join:
select
ct.column_id,
case ct.column_id
when 1 then cv.FirstName
when 2 then cv.LastName
when 4 then cv.Phone
end column_value
from #column_table ct cross join #column_value cv
where ct.column_id <> 3
See the demo

How to sum values of multiple columns in SQL Server

SELECT
name
FROM
sys.all.column
WHERE object_id = (SELECT object_id
FROM sys.all_objects
WHERE name ='name of my table' and type = 'TT')
AND name NOT IN (list of columns that I don't need)
How do I sum all the values of the returned columns from the preceding SQL query?
Another option which does not require dynamic SQL, but only a CROSS APPLY or two
Just for fun, I add Min, Max, and Avg just to illustrate... Also added a PctOfTotal or Common-Size
Declare #YourTable table (ID int,CustName varchar(50),Sales_Jan int,Sales_Feb int,Sales_Mar int)
Insert into #YourTable values
(1,'John Smith',25,25,50),
(2,'Jane Doe' ,35,20,null)
Select A.*
,C.*
,PctOfTotal = Format(C.Total*1.0/Sum(C.Total) over (),'0.00%')
From #YourTable A
Cross Apply (Select XMLData=cast((Select A.* For XML RAW) as xml)) B
Cross Apply (
Select Total = Sum(Value)
,Min = Min(Value)
,Max = Max(Value)
,Avg = Avg(Value)
From (
Select Value = attr.value('.','int')
From B.XMLData.nodes('/row') as A(r)
Cross Apply A.r.nodes('./#*') AS B(attr)
Where attr.value('local-name(.)','varchar(100)') Like 'Sales_%'
--Or you can Exclude Specific Columns
--Where attr.value('local-name(.)','varchar(100)') not in ('ID','CustName')
) S
) C
Returns
If I understand correctly, you want to find out some columns from meta tables that you want to sum, and then sum those columns on the given table. You can use dynamic SQL to achieve this:
create table t(a integer, b integer, c integer);
insert into t values(1,2,3);
declare #tab varchar(100);
declare #sql varchar(max);
set #sql = '';
set #tab = 't';
select #sql = #sql + '+' + a.name from sys.all_columns a
inner join
sys.all_objects b
on a.object_id = b.object_id
where b.name = #tab
and a.name not in ('c');
set #sql = 'select ' + stuff(#sql, 1, 1, '') + ' from ' + #tab;
exec(#sql);
Produces:
3
select col1,col2,col3,col4,NVL(col1,0)+NVL(col2,0)+NVL(col3,0)+NVL(col4,0)
from
(select *
from sys.all.column
where object_id =(select object_id from sys.all.object where name ='name of my table')
and name not in (list of columns that I dont need).)
A | B | Total(col1+col2)
------+------+-------
1 | 2 | 3
---------------------
1 | | 1
Whatever columns you get, sum it and put them as seperate column in the result table.

how can I use Pivot using a variable in SQL?

I have paycode numbers and Names from table Paycodes
and I have Amount in monthlyTransaction. as follows:
Paycodes
Code Name
1 Basic Salary
2 Variable Deduction Amount
3 Fixed/Var Insurance PayCode
MonthlyTransaction
Code Amount
1 3000
2 10000
1 130000
1 150000
3 120000
I want it to be like this using pivot
Basic Salary Variable Deduction Amount Fixed/Var Insurance PayCode
31000 10000 120000
I want to use pivot to sum the Amount of each Paycode and I used this:-
DECLARE #data AS NVARCHAR(MAX)
DECLARE #query AS NVARCHAR(MAX)
-- DECLARE #data TABLE
--(
-- PaycodeName NVARCHAR(max)
--)
--INSERT INTO #data
-- ( PaycodeName )
--select dbo.Paycode.PayCodeName FROM dbo.Paycode
select #data = Paycode.PayCodeName FROM Paycode
set #query = 'SELECT * FROM (
SELECT Paycode.Name , MonthlyTransaction.Amount
From MonthlyTransaction
LEFT JOIN dbo.Paycode ON Paycode.code = MonthlyTransaction.Paycode
) AS s
PIVOT
(
SUM(Amount)
FOR Paycode.Name IN ('+#data+')
) AS pvt '
EXECUTE Sp_executesql #query
When I print #data it retrieve the last paycode only !
Can anyone help ?
To get all the paycodes in #data use
SELECT #data = #data + Paycode.PayCodeName + ', '
FROM Paycode
Then remove the last comma
the answer is :
DECLARE #codeNameCol NVARCHAR(max)
SELECT #codeNameCol= COALESCE(#codeNameCol + ',','') + QUOTENAME(RTRIM(LTRIM(PayCodeName)))
FROM (SELECT DISTINCT PayCodeName FROM Paycode) AS codeNameCol
DECLARE #querys NVARCHAR(max)
Set #querys='
SELECT *
FROM ( SELECT dbo.EmpAssignment.EmployeeId ,
PayCodeName ,
Amount
FROM dbo.MonthlyTransaction
LEFT JOIN dbo.Paycode ON Paycode.code = MonthlyTransaction.Paycode
LEFT JOIN dbo.EmpAssignment ON EmpAssignment.EmpId = MonthlyTransaction.EmpId
LEFT JOIN dbo.PayrollGroup ON PayrollGroup.PayrollGroup = EmpAssignment.PayrollGroup
) DataTable PIVOT
( SUM(Amount) FOR PayCodeName IN ( '+#codeNameCol+' ) ) PivotTable;'
EXEC (#querys)
This should do the trick
SELECT 1 Code, 'Basic Salary' Name
INTO #Paycode
UNION
SELECT 2 Code, 'Variable Deduction Amount' Name
UNION
SELECT 3 Code, 'Fixed/Var Insurance PayCode' Name
SELECT 1 Code, 3000 Amount
INTO #MonthTrans
UNION
SELECT 2 Code, 10000 Amount
UNION
SELECT 1 Code, 130000 Amount
UNION
SELECT 1 Code, 150000 Amount
UNION
SELECT 3 Code, 120000 Amount
DECLARE #data AS NVARCHAR(MAX)
SELECT #data = ISNULL(#data,'') + '[' +CAST(Code AS varchar) + '], '
FROM #Paycode
SELECT #data=SUBSTRING(#data, 0, LEN(#data))
DECLARE #query AS NVARCHAR(MAX)
SELECT #query = 'SELECT *
FROM
#MonthTrans M
PIVOT (
SUM(Amount) FOR Code IN (' + #data + ')
) pvt'
EXECUTE Sp_executesql #query
drop table #paycode
drop table #MonthTrans

Dynamic SELECT statement, generate columns based on present and future values

Currently building a SELECT statement in SQL Server 2008 but would like to make this SELECT statement dynamic, so the columns can be defined based on values in a table. I heard about pivot table and cursors, but seems kind of hard to understand at my current level, here is the code;
DECLARE #date DATE = null
IF #date is null
set # date = GETDATE() as DATE
SELECT
Name,
value1,
value2,
value3,
value4
FROM ref_Table a
FULL OUTER JOIN (
SELECT
PK_ID ID,
sum(case when FK_ContainerType_ID = 1 then 1 else null) Box,
sum(case when FK_ContainerType_ID = 2 then 1 else null) Pallet,
sum(case when FK_ContainerType_ID = 3 then 1 else null) Bag,
sum(case when FK_ContainerType_ID = 4 then 1 else null) Drum
from
Packages
WHERE
#date between PackageStart AND PackageEnd
group by PK_ID ) b on a.Name = b.ID
where
Group = 0
The following works great for me , but PK_Type_ID and the name of the column(PackageNameX,..) are hard coded, I need to be dynamic and it can build itself based on present or futures values in the Package table.
Any help or guidance on the right direction would be greatly appreciated...,
As requested
ref_Table (PK_ID, Name)
1, John
2, Mary
3, Albert
4, Jane
Packages (PK_ID, FK_ref_Table_ID, FK_ContainerType_ID, PackageStartDate, PackageEndDate)
1 , 1, 4, 1JAN2014, 30JAN2014
2 , 2, 3, 1JAN2014, 30JAN2014
3 , 3, 2, 1JAN2014, 30JAN2014
4 , 4, 1, 1JAN2014, 30JAN2014
ContainerType (PK_ID, Type)
1, Box
2, Pallet
3, Bag
4, Drum
and the result should look like this;
Name Box Pallet Bag Drum
---------------------------------------
John 1
Mary 1
Albert 1
Jane 1
The following code like I said works great, the issue is the Container table is going to grow and I need to replicated the same report without hard coding the columns.
What you need to build is called a dynamic pivot. There are plenty of good references on Stack if you search out that term.
Here is a solution to your scenario:
IF OBJECT_ID('tempdb..##ref_Table') IS NOT NULL
DROP TABLE ##ref_Table
IF OBJECT_ID('tempdb..##Packages') IS NOT NULL
DROP TABLE ##Packages
IF OBJECT_ID('tempdb..##ContainerType') IS NOT NULL
DROP TABLE ##ContainerType
SET NOCOUNT ON
CREATE TABLE ##ref_Table (PK_ID INT, NAME NVARCHAR(50))
CREATE TABLE ##Packages (PK_ID INT, FK_ref_Table_ID INT, FK_ContainerType_ID INT, PackageStartDate DATE, PackageEndDate DATE)
CREATE TABLE ##ContainerType (PK_ID INT, [Type] NVARCHAR(50))
INSERT INTO ##ref_Table (PK_ID,NAME)
SELECT 1,'John' UNION
SELECT 2,'Mary' UNION
SELECT 3,'Albert' UNION
SELECT 4,'Jane'
INSERT INTO ##Packages (PK_ID, FK_ref_Table_ID, FK_ContainerType_ID, PackageStartDate, PackageEndDate)
SELECT 1,1,4,'2014-01-01','2014-01-30' UNION
SELECT 2,2,3,'2014-01-01','2014-01-30' UNION
SELECT 3,3,2,'2014-01-01','2014-01-30' UNION
SELECT 4,4,1,'2014-01-01','2014-01-30'
INSERT INTO ##ContainerType (PK_ID, [Type])
SELECT 1,'Box' UNION
SELECT 2,'Pallet' UNION
SELECT 3,'Bag' UNION
SELECT 4,'Drum'
DECLARE #DATE DATE, #PARAMDEF NVARCHAR(MAX), #COLS NVARCHAR(MAX), #SQL NVARCHAR(MAX)
SET #DATE = '2014-01-15'
SET #COLS = STUFF((SELECT DISTINCT ',' + QUOTENAME(T.[Type])
FROM ##ContainerType T
FOR XML PATH, TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #SQL = 'SELECT [Name], ' + #COLS + '
FROM (SELECT [Name], [Type], 1 AS Value
FROM ##ref_Table R
JOIN ##Packages P ON R.PK_ID = P.FK_ref_Table_ID
JOIN ##ContainerType T ON P.FK_ContainerType_ID = T.PK_ID
WHERE #DATE BETWEEN P.PackageStartDate AND P.PackageEndDate) X
PIVOT (COUNT(Value) FOR [Type] IN (' + #COLS + ')) P
'
PRINT #COLS
PRINT #SQL
SET #PARAMDEF = '#DATE DATE'
EXEC SP_EXECUTESQL #SQL, #PARAMDEF, #DATE=#DATE
Output:
Name Bag Box Drum Pallet
Albert 0 0 0 1
Jane 0 1 0 0
John 0 0 1 0
Mary 1 0 0 0
Static Query:
SELECT [Name],[Box],[Pallet],[Bag],[Drum] FROM
(
SELECT *
FROM
(
SELECT rf.Name,cnt.[Type], pk.PK_ID AS PKID, rf.PK_ID AS RFID
FROM ref_Table rf INNER JOIN Packages pk ON rf.PK_ID = pk.FK_ref_Table_ID
INNER JOIN ContanerType cnt ON cnt.PK_ID = pk.FK_ContainerType_ID
) AS SourceTable
PIVOT
(
COUNT(PKID )
FOR [Type]
IN ( [Box],[Pallet],[Bag],[Drum])
) AS PivotTable
) AS Main
ORDER BY RFID
Dynamic Query:
DECLARE #columnList nvarchar (MAX)
DECLARE #pivotsql nvarchar (MAX)
SELECT #columnList = STUFF(
(
SELECT ',' + '[' + [Type] + ']'
FROM ContanerType
FOR XML PATH( '')
)
,1, 1,'' )
SET #pivotsql =
N'SELECT [Name],' + #columnList + ' FROM
(
SELECT *
FROM
(
SELECT rf.Name,cnt.[Type], pk.PK_ID AS PKID, rf.PK_ID AS RFID
FROM ref_Table rf INNER JOIN Packages pk ON rf.PK_ID = pk.FK_ref_Table_ID
INNER JOIN ContanerType cnt ON cnt.PK_ID = pk.FK_ContainerType_ID
) AS SourceTable
PIVOT
(
COUNT(PKID )
FOR [Type]
IN ( ' + #columnList + ')
) AS PivotTable
) AS Main
ORDER BY RFID;'
EXEC sp_executesql #pivotsql
Following my tutorial below will help you to understand the PIVOT functionality:
We write sql queries in order to get different result sets like full, partial, calculated, grouped, sorted etc from the database tables. However sometimes we have requirements that we have to rotate our tables. Sounds confusing?
Let's keep it simple and consider the following two screen grabs.
SQL Table:
Expected Results:
Wow, that's look like a lot of work! That is a combination of tricky sql, temporary tables, loops, aggregation......, blah blah blah
Don't worry let's keep it simple, stupid(KISS).
MS SQL Server 2005 and above has a function called PIVOT. It s very simple to use and powerful. With the help of this function we will be able to rotate sql tables and result sets.
Simple steps to make it happen:
Identify all the columns those will be part of the desired result set.
Find the column on which we will apply aggregation(sum,ave,max,min etc)
Identify the column which values will be the column header.
Specify the column values mentioned in step3 with comma separated and surrounded by square brackets.
So, if we now follow above four steps and extract information from the above sales table, it will be as below:
Year, Month, SalesAmount
SalesAmount
Month
[Jan],[Feb] ,[Mar] .... etc
We are nearly there if all the above steps made sense to you so far.
Now we have all the information we need. All we have to do now is to fill the below template with required information.
Template:
Our SQL query should look like below:
SELECT *
FROM
(
SELECT SalesYear, SalesMonth,Amount
FROM Sales
) AS SourceTable
PIVOT
(
SUM(Amount )
FOR SalesMonth
IN ( [Jan],[Feb] ,[Mar],
[Apr],[May],[Jun] ,[Jul],
[Aug],[Sep] ,[Oct],[Nov] ,[Dec])
) AS PivotTable;
In the above query we have hard coded the column names. Well it's not fun when you have to specify a number of columns.
However, there is a work arround as follows:
DECLARE #columnList nvarchar (MAX)
DECLARE #pivotsql nvarchar (MAX)
SELECT #columnList = STUFF(
(
SELECT ',' + '[' + SalesMonth + ']'
FROM Sales
GROUP BY SalesMonth
FOR XML PATH( '')
)
,1, 1,'' )
SET #pivotsql =
N'SELECT *
FROM
(
SELECT SalesYear, SalesMonth,Amount
FROM Sales
) AS SourceTable
PIVOT
(
SUM(Amount )
FOR SalesMonth
IN ( ' + #columnList +' )
) AS PivotTable;'
EXEC sp_executesql #pivotsql
Hopefully this tutorial will be a help to someone somewhere.
Enjoy coding.

Not able to formulate query to combine different row values in single row using pivot table

Below is the actual table
In the table above:
1) FEID is the examination ID which remains same for one exam, like ist semester examination of particular class. So it will remain same for all rows in above table as it consists of data of single exam always.
2) To store result of single student, marks for each subject are entered in each row. So if there are 5 subjects in a class,For each student marks of 5 subjects will be stored in 5 separate rows with marks obtained in each subject
3) Result, Result_code, NCHMCTID remain same in each row of single student. Like in above table, their values remain same in 3 rows.
Due to some reasons I cant remove this redundancy
So my question is, I need to store result of one student in single row, but number of rows related to single student to store each subject marks is not pre determined(number of subjects can change and determined dynamically)
So , if I have 5 subjects marks in 5 rows, I need those in single row.
Below is exactly what I need to convert above table into:
Above there are only 3 subjects, but they can be more than 3 subjects also.
To get subjects list, I use below query for the same and get subjects like:
[vb],[c(p)],VB(p) stored in single variable which I was trying to use in pivot table.
DECLARE #values varchar(max);
SET #values = '';
SELECT #values = #values +'['+ CAST(SubjectName AS varchar(max))+ ']' + ','
FROM tbSubjects where SubID IN(Select SubID from tbFinalMarks Where FEID=2) ;
SET #values = SUBSTRING(#values, 1, Len(#values) - 1)
Full procedure is below :
ALTER PROCEDURE [dbo].[prFinalMarksLoadByFEID]
#FEID int
AS
BEGIN
SET NOCOUNT ON;
DECLARE #values varchar(max);
SET #values = '';
SELECT #values = #values +'['+ CAST(SubjectName AS varchar(max))+ ']' + ','
FROM tbSubjects where SubID IN(Select SubID from tbFinalMarks Where FEID=2) ;
SET #values = SUBSTRING(#values, 1, Len(#values) - 1)
SELECT #values As 'Values'
select Student_Name,#values,Result,NCHMCTID,Examination_Name from
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
(SELECT dbo.tbStudent.Name AS Student_Name, dbo.tbSubjects.SubjectName AS Subject_Name, dbo.tbFinalMarks.MarksObtained AS Marks_Obtained,
dbo.tbFinalMarks.Result, dbo.tbFinalMarks.ResultCode AS Result_Code, ISNULL(dbo.tbStudent.NCHMCTID, 'Not Available') AS NCHMCTID,
dbo.tbFinalExam.ExaminationName as Examination_Name
FROM dbo.tbFinalMarks INNER JOIN
dbo.tbSubjects ON dbo.tbFinalMarks.SubID = dbo.tbSubjects.SubID INNER JOIN
dbo.tbStudent ON dbo.tbFinalMarks.StdID = dbo.tbStudent.StudentID INNER JOIN
dbo.tbFinalExam ON dbo.tbFinalMarks.FEID = dbo.tbFinalExam.FEID
Where FEID =#FEID
) ps
PIVOT
(
MAX(Marks_Obtained) For Subject_Name IN ([VB],[VB(P)],[C(P)])
) AS pvt
But I am not able to do it. Please help
Below part give me actual table which i need to manipulate for result table
(SELECT dbo.tbStudent.Name AS Student_Name, dbo.tbSubjects.SubjectName AS Subject_Name, dbo.tbFinalMarks.MarksObtained AS Marks_Obtained,
dbo.tbFinalMarks.Result, dbo.tbFinalMarks.ResultCode AS Result_Code, ISNULL(dbo.tbStudent.NCHMCTID, 'Not Available') AS NCHMCTID,
dbo.tbFinalExam.ExaminationName as Examination_Name
FROM dbo.tbFinalMarks INNER JOIN
dbo.tbSubjects ON dbo.tbFinalMarks.SubID = dbo.tbSubjects.SubID INNER JOIN
dbo.tbStudent ON dbo.tbFinalMarks.StdID = dbo.tbStudent.StudentID INNER JOIN
dbo.tbFinalExam ON dbo.tbFinalMarks.FEID = dbo.tbFinalExam.FEID
Where FEID =#FEID
)
I used [vb],[vb(p)],[C(P)] instead of #values ( it contains subjects list) as using # values in below part gives me error:
PIVOT
(
MAX(Marks_Obtained) For Subject_Name IN ([VB],[VB(P)],[C(P)])
) AS pvt
Below is the data:
FEID Student_Name Subject_Name Marks_Obtained Result Result_Code NCID Exam_Name
2 roof VB 100 First 1234 ist semester
2 roof VB(P) 100 First 1234 ist semester
2 roof C(P) 100 First 1234 ist semester
2 Amir VB 100 First nbb 8 ist semester
2 Amir VB(P) 100 First nbb 8 ist semester
2 Amir C(P) 100 First nbb 8 ist semester
Here's your query:
create table #t (FEID int, Student_Name char(4), Subject_Name char(5), Marks_Obtained int,
Result char(5), Result_Code int, NCID char(5), Exam_Name char(12))
go
insert #t values
( 2, 'roof', 'VB ', 100, 'First', NULL, '1234 ', 'ist semester'),
( 2, 'roof', 'VB(P)', 100, 'First', NULL, '1234 ', 'ist semester'),
( 2, 'roof', 'C(P) ', 100, 'First', NULL, '1234 ', 'ist semester'),
( 2, 'Amir', 'VB ', 100, 'First', NULL, 'nbb 8', 'ist semester'),
( 2, 'Amir', 'VB(P)', 100, 'First', NULL, 'nbb 8', 'ist semester'),
( 2, 'Amir', 'C(P) ', 100, 'First', NULL, 'nbb 8', 'ist semester')
go
declare #collist nvarchar(max)
SET #collist = stuff((select distinct ',' + QUOTENAME(subject_name)
FROM #t -- your table here
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #collist
declare #q nvarchar(max)
set #q = '
select *
from (
select
Student_Name, subject_name, Marks_Obtained, Exam_Name, Result, NCID, Result_Code
from (
select *
from #t -- your table here
) as x
) as source
pivot (
max(Marks_Obtained)
for subject_name in (' + #collist + ')
) as pvt
'
exec (#q)