left join of 3 tables and display like a dynamic pivot - sql

i have 3 tables:
payorderType :
---------
typeID | TypeName |
1 | accounting |
2 | budget |
----------
step:
----------
StepID | StepName | typeID
1 | payorder | 1
2 | cheque | 1
3 | cheque | 2
----------
user:
----------
userID | StepName | StepID
7878 | payorder | 1
4547 | cheque | 2
6538 | cheque | 1
----------
I want to make a table which users exists in row and columns includes with concat of step and payorderType. same as below:
users | accounting_payorder | accounting_cheque | budget_cheque |
7878 | 1 | 0 | 0 |
4547 | 0 | 1 | 0 |
6538 | 0 | 1 | 0 |
My quesdtion is : if i don't know number of payorderType rows and number of step rows, how should i write it?
My Script is here :
First I create a table in cursor for concat payorderType and step:
CREATE PROC sp_payOrderType
AS
BEGIN
DECLARE a CURSOR
FOR SELECT DISTINCT p.TypeName,s.StepName
FROM
dbo.PayOrderType p LEFT JOIN
dbo.vStep s ON s.TypeID = p.TypeID
FOR READ ONLY
DECLARE #payOrderType NVARCHAR(50),#stepName NVARCHAR(50)
DECLARE #SQL NVARCHAR(MAX)=''
OPEN a
FETCH NEXT FROM a INTO #payOrderType, #stepName
WHILE ##FETCH_STATUS=0
BEGIN
DECLARE #b VARCHAR(max), #b2 VARCHAR(max)
SELECT #b = ISNULL(#b ,'') +'['+ ISNULL(#payOrderType ,'')+ '____'+ISNULL(#stepName ,'')+ ']'+ ' NVARCHAR(1000) ,'
FETCH NEXT FROM a INTO #payOrderType,#stepName
END
CLOSE a
DEALLOCATE a
SELECT #SQL = 'ALTER table AA(' + SUBSTRING(#b,1, LEN(#b)-1) + ')'
SELECT #SQL
END
but i don't know how i should relate rows(userID) with columns ?

You should have determined output structure. Its little risky to have variable output structure.
But here we go:
Make your structure simple (remove most of variables) - create view (or use derived table) payorderType + step
-- should be inner join probably instead of left join
-- if you use left join you have to isnull s.StepName
SELECT
u.userID,
s.StepID,
p.TypeName,
s.StepName,
p.TypeName + '_' + s.StepName StepType,
-- Your column can be like `coalesce(p.TypeName + '_' + s.StepName, p.TypeName, s.StepName) StepType` for left joins
1 Point
FROM dbo.PayOrderType p
INNER JOIN dbo.vStep s ON s.TypeID = p.TypeID
INNER JOIN dbo.user u ON u.StepID = s.StepID
Make your queries more clear (can all yours fields have null values?. Now you can work with only one column/variable.
Now is time for pivot:
SELECT
userID,
[accounting_payorder],
[accounting_cheque],
[budget_cheque]
FROM newview v
PIVOT(MAX(point) FOR StepType in ([accounting_payorder], [accounting_cheque], [budget_cheque])
If its necessary you can use dynamic query:
declare #header varchar(max),
#columns varchar(max)
select #header = coalesce(#header + ', ', '') + 'isnull(''' + StepType + ''', 0) ' + '[' + StepType + ']',
#columns = coalesce(#columns + ', ', '') + '[' + StepType + ']'
from newview
group by StepType
declare #sqlpvt varchar(4000) -- limited by lenght of exec statement
set #sqlpvt = 'select userID, $HEADER FROM newview v PIVOT(MAX(point) FOR StepType in ($COLUMNS)'
-- replace pseudovariables
set #sqlpvt = replace(#sqlpvt, '$HEADER', #header)
set #sqlpvt = replace(#sqlpvt, '$COLUMNS', #columns)
print #sqlpvt
exec (#sqlpvt)
Sorry if somethink is wrong (writed on blind), but i think for guide it's enough. But you should prefer end on step 2 (non-static code is dangerous).

Related

SQL combine three rows into one column

Is there any way to solve this? I am practicing SQL and I don't know how to do this.
Image table
----------------------------
| prdctCode | imgPath |
| P0003 | P0003-1.jpg |
| P0003 | P0003-2.jpg |
| P0003 | P0003-3.jpg |
| P0004 | P0004-1.jpg |
| P0004 | P0004-2.jpg |
| P0004 | P0004-3.jpg |
----------------------------
Product table
-------------------------
| prdctCode | prdctName |
| P0003 | Hand Bag |
| P0004 | Pencil |
-------------------------
What I get
---------------------------------------
| prdctCode | prdctName | imgPath |
| P0003 | Hand Bag | P0003-1.jpg |
| P0003 | Hand Bag | P0003-2.jpg |
| P0003 | Hand Bag | P0003-3.jpg |
| P0004 | Pencil | P0004-1.jpg |
| P0004 | Pencil | P0004-2.jpg |
| P0004 | Pencil | P0004-3.jpg |
---------------------------------------
Expected output
--------------------------------------------------------------------
| prdctCode | prdctName | imgPath1 | imgPath2 | imgPath3 |
| P0003 | Hand Bag | P0003-1.jpg | P0003-2.jpg | P0003-3.jpg |
| P0004 | Pencil | P0004-1.jpg | P0004-2.jpg | P0004-3.jpg |
--------------------------------------------------------------------
This is my code
select prdTbl.prdctCode, prdTbl.prdctName, imgTbl.imgPath
from [product_tbl]prdTbl left join [image_tbl]imgTbl
on prdTbl.prdctCode = imgTbl.prdctCode
I'm not sure if this is possible.
If you know for sure that for a product will always be maximum 4 images and that the image is always ending with .jpg, maybe this select can help:
select prdTbl.prdctCode, prdTbl.prdctName, imgTbl2.imgPath as Path1, imgTbl2.imgPath as Path2, imgTbl3.imgPath as Path3, imgTbl4.imgPath as Path4
from [product_tbl]prdTbl
left join [image_tbl]imgTbl1 on prdTbl.prdctCode = imgTbl1.prdctCode and imgTbl1.imgPath like '%-1.jpg'
left join [image_tbl]imgTbl2 on prdTbl.prdctCode = imgTbl2.prdctCode and imgTb12.imgPath like '%-2.jpg'
left join [image_tbl]imgTbl3 on prdTbl.prdctCode = imgTbl3.prdctCode and imgTbl3.imgPath like '%-3.jpg'
left join [image_tbl]imgTbl4 on prdTbl.prdctCode = imgTbl4.prdctCode and imgTbl4.imgPath like '%-4.jpg'
Please consider looking at that script :
CREATE TABLE #TempAppointmentTable (
UniqueID VARCHAR(MAX),
VAL nvarchar(500)
);
INSERT INTO #TempAppointmentTable
([UniqueID], [VAL])
VALUES
('P0003', 'P0003-1.jpg'),
('P0003', 'P0003-2.jpg'),
('P0003', 'P0003-3.jpg'),
('P0004', 'P0004-1.jpg'),
('P0004', 'P0004-2.jpg')
;
DECLARE #list_id TABLE (idx INT IDENTITY, id VARCHAR(MAX))
DECLARE #nb_rows INT
DECLARE #nb_cols INT
DECLARE #i INT = 0
DECLARE #j INT = 0
DECLARE #cur_id VARCHAR(MAX)
DECLARE #cur_nb_rows INT
DECLARE #sql VARCHAR(MAX)
INSERT INTO #list_id(id) SELECT [UniqueID] FROM #TempAppointmentTable GROUP BY [UniqueID] ORDER BY COUNT(*) DESC;
SELECT #nb_rows = COUNT(*) FROM #list_id;
SELECT #nb_cols = MAX(val) FROM (SELECT COUNT(*) FROM #TempAppointmentTable GROUP BY [UniqueID])t(val);
SET #sql = '
WITH TMP ([Row], [UniqueID], [VAL]) AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY [UniqueID] ORDER BY UniqueID), [UniqueID], [VAL] from #TempAppointmentTable
)'
WHILE #i < #nb_rows
BEGIN
SELECT #cur_id = id FROM #list_id WHERE idx = #i+1
SELECT #cur_nb_rows = COUNT(*) FROM #TempAppointmentTable WHERE [UniqueID] = #cur_id
IF #i != 0
SET #sql = #sql + '
UNION'
SET #sql = #sql + '
SELECT TMP' + CONVERT(VARCHAR,#i) + '0.[UniqueID], TMP' + CONVERT(VARCHAR,#i) + '0.[VAL]'
WHILE #j+1 < #nb_cols
BEGIN
SET #j = #j + 1
IF #j < #cur_nb_rows
SET #sql = #sql + ', TMP'+ CONVERT(VARCHAR,#i) + CONVERT(VARCHAR,#j) + '.[VAL] AS [VAL' + CONVERT(VARCHAR,#j) + ']'
ELSE
SET #sql = #sql + ', NULL'
END
SET #j = 0
SET #sql = #sql + '
FROM TMP AS TMP' + CONVERT(VARCHAR,#i) + '0'
WHILE #j+1 < #nb_cols
BEGIN
SET #j = #j + 1
IF #j < #cur_nb_rows
SET #sql = #sql + '
INNER JOIN TMP AS TMP' + CONVERT(VARCHAR,#i) + CONVERT(VARCHAR,#j) + ' ON TMP' + CONVERT(VARCHAR,#i) + CONVERT(VARCHAR,#j) + '.Row = ' + CONVERT(VARCHAR,#j+1) +' AND TMP' + CONVERT(VARCHAR,#i) + CONVERT(VARCHAR,#j) + '.UniqueID = ''' + CONVERT(VARCHAR,#cur_id) + ''''
END
SET #sql = #sql + '
WHERE TMP' + CONVERT(VARCHAR,#i) + '0.Row = 1 AND TMP' + CONVERT(VARCHAR,#i) + '0.UniqueID = ''' + CONVERT(VARCHAR,#cur_id) + ''''
SET #j = 0
SET #i = #i + 1
END
PRINT(#sql)
EXEC(#sql)
Drop table #TempAppointmentTable
The output is
UniqueID
VAL
VAL1
VAL2
P0003
P0003-1.jpg
P0003-2.jpg
P0003-3.jpg
P0004
P0004-1.jpg
P0004-2.jpg
NULL
As you can see it considers the number of elements, so the day you'll have 100 rows for a product (p0003 or any other) it will have 101 columns :D
You can modify that script for your neeeds
I hope it can feets your needs
For any other question I'll be right there

Dynamic Pivot Table across multiple columns

I'm a fairly new to SQL and could use some help. I have a table of time sheet data with a separate time sheet on each row. Each time sheet has a column with jobcode1 to jobcode16 that stores a string indicating a job code. Each of those has a corresponding TotalJob1 to TotalJob16.
I've managed to create a pivot on the JobCode1 no problem with a column for each Job and the total from TotalJob1. I used this to build it.
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
SELECT #ColumnName = ISNULL(#ColumnName + ',','') + QUOTENAME(TS_Job1Code)
FROM (SELECT DISTINCT TS_Job1Code FROM
dbo.timesheetData) as timesheetdata
SET #DynamicPivotQuery =
N'SELECT VolumeID, ' + #ColumnName + '
FROM dbo.timesheetData
PIVOT(SUM(TS_TotalJob1)
FOR TS_Job1Code IN (' + #ColumnName + ')) AS PVTTable'
EXEC sp_executesql #DynamicPivotQuery
I'm struggling to iterate over the other Job columns and merge them into one big pivot table and was hoping someone might be able to give me a pointer?
My thought was to try and repeat the step 16 times but I don't think this is even close to the right way.
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
DECLARE #N AS INT
DECLARE #NCHAR AS NVARCHAR(MAX)
SET #N = 1
WHILE #N < 17
BEGIN
SET #NCHAR = CAST(#N as VARCHAR)
SELECT #ColumnName = ISNULL(#ColumnName + ',','') + QUOTENAME(('TS_Job' +
#NCHAR + 'Code'))
FROM (SELECT DISTINCT ('TS_Job' + #NCHAR + 'Code') FROM
dbo.timesheetData) as timesheetdata
SET #DynamicPivotQuery =
N'SELECT ' + #ColumnName + '
FROM dbo.timesheetData
PIVOT(SUM(TS_TotalJob' + #NCHAR + ')
FOR TS_Job' + #NCHAR + 'Code IN (' + #ColumnName + ')) AS PVTTable'
EXEC sp_executesql #DynamicPivotQuery
SET #N = #N + 1
END
EXEC sp_executesql #SQL
Original
+-------------+----------+----------+----------+-----------+-----------+-----------+
| TimesheetID | JobCode1 | JobCode2 | JobCode3 | TotalJob1 | TotalJob2 | TotalJob3 |
+-------------+----------+----------+----------+-----------+-----------+-----------+
| 1 | J1 | J3 | | 10 | 9 | |
+-------------+----------+----------+----------+-----------+-----------+-----------+
| 2 | J2 | J1 | J3 | 5 | 5 | 5 |
+-------------+----------+----------+----------+-----------+-----------+-----------+
| 3 | J2 | | | 6 | 3 | 1 |
+-------------+----------+----------+----------+-----------+-----------+-----------+
What I want to achieve
+-------------+----+----+----+----+----+
| TimesheetID | J1 | J2 | J3 | J4 | J6 |
+-------------+----+----+----+----+----+
| 1 | 10 | | 9 | | |
+-------------+----+----+----+----+----+
| 2 | 5 | 5 | 5 | | |
+-------------+----+----+----+----+----+
| 3 | | 6 | | 3 | 1 |
+-------------+----+----+----+----+----+
It's going to get painfully complicated, but one thing you can do is to UNPIVOT your data so that it looks like this:
TimesheetId JobCode JobTotal
1 J1 10
1 J3 9
2 J1 5
....
And then PIVOT that derived table to get your desired result.
Like Tab mentioned, you can unpivot your data first and then Pivot it again.
You can use CROSS APPLY and VALUES to unpivot your table into a temp table.
SELECT ca.*
INTO #temp
FROM timesheet
CROSS APPLY (VALUES
(TimesheetID, JobCode1, TotalJob1),
(TimesheetID, JobCode2, TotalJob2),
(TimesheetID, JobCode3, TotalJob3)
) ca(TimesheetID, JobCode, TotalJob)
this gives you a table like
TimesheetID JobCode TotalJob
----------- ------- -----------
1 J1 10
1 J3 9
1 NULL NULL
2 J2 5
2 J1 5
2 J3 5
3 J2 6
3 NULL 3
3 NULL 1
not sure if you'd have null jobcodes in actual data.. but you can eliminate them using Where ca.JobCode IS NOT NULL above
Then you create your dynamic column string from the temp table
DECLARE #JobCodes nvarchar(MAX)
SELECT #JobCodes = COALESCE(#JobCodes + ',','') + QUOTENAME(JobCode)
FROM #temp
GROUP BY JobCode
ORDER BY JobCode
Then build your dynamic pivot. Instead of creating global temp table, just use the same query before in your pivot query.
DECLARE #Sql nvarchar(max)
SET #Sql = N'
SELECT TimeSheetID,' + #JobCodes
+ 'FROM (
SELECT ca.*
FROM timesheet
CROSS APPLY (VALUES
(TimesheetID, JobCode1, TotalJob1),
(TimesheetID, JobCode2, TotalJob2),
(TimesheetID, JobCode3, TotalJob3)
) ca(TimesheetID, JobCode, TotalJob)
) t
PIVOT (
SUM(TotalJob)
FOR JobCode IN (' + #JobCodes + ')
) p'
EXEC sp_executesql #Sql

Execute stored procedure with parameter from other table

I have a procedure with one parameter, letsay #AssetID int.
I want to select a column value from another table, then use that value as the parameter for this procedure.
I've stored procedure something like this and the table has been filtered with "Where" criteria from #AssetID parameter:
declare #inspectyear as nvarchar(max), #calc as nvarchar(max), #query as nvarchar(max);
set #inspectyear = STUFF((select distinct ',' + quotename(InspectYear) from ##t2 c
for XML path(''), type).value('.','NVARCHAR(MAX)'),1,1,'')
select #calc = ', ' + quotename(Max(InspectYear)) + ' - ' + quotename(Max(InspectYear)-2)
+ ' as Calc1, ' + quotename(Max(InspectYear)) + ' - ' + quotename(min(InspectYear))
+ ' as Calc2' from #t2;
set #query =
';with data as
(
select inspectyear,
partno, Pos, number
from #t2
unpivot
(
number
for Pos in ([Pos1], [Pos2], [Pos3], [Pos4])
) unpvt
)
select * ' + #calc + ' into ##temp
from data
pivot
(
sum(number)
for inspectyear in (' + #inspectyear + ')
) pvt
order by partno';
exec sp_executesql #query = #query;
select * from ##temp;
drop table ##temp;
So I need to create another procedure, for instance:
create procedure spExecmyProc
as
begin
exec spMyProc '#AssetID' -- <-- The parameter took from other table.
go
end
The #date parameter, took from other table.
Is it possible to do that? The result should be only one result.
So far, this is what I did. It works, but the result is not on "one result". It create more than one result if the #AssetID is more than one:
declare #AssetID int;
declare cur CURSOR FOR
select distinct AssetID from myTable
open cur
fetch next from cur into #AssetID
while ##FETCH_STATUS = 0
begin
exec mySPName #AssetID
fetch next from cur into #AssetID
end
close cur
DEALLOCATE cur
Thank you.
I'm not 100% sure I understand what you're trying to achieve, but if you want to be able to be able to run some code on each value of AssetID in mytable, returning just one result for each input value, I think you could use a Scalar-valued Function. Let's pretend that the purpose of your original stored procedure was just to increment the AssetId value by 1 for simplicity - your function could be created like this:
CREATE FUNCTION fnMyFunction (#AssetId INT)
RETURNS INT
AS
BEGIN
DECLARE #return INT
SET #return = #AssetId + 1
RETURN #return
END
If you then have some values in a table:
CREATE TABLE Assets (
AssetId INT
)
INSERT INTO Assets
SELECT 1
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 5
UNION
SELECT 7
UNION
SELECT 5
You can call your function on each value you return:
SELECT AssetId,
dbo.fnMyFunction(AssetId) AS AssetIdPlus1
FROM Assets
Which gives these results for my super simple dataset defined above:
/------------------------\
| AssetId | AssetIdPlus1 |
|---------+--------------|
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
| 5 | 6 |
| 7 | 8 |
| 5 | 6 |
\------------------------/
If you just want to get the result for each unique value of AssetId in your table, then just return the DISTINCT results:
SELECT DISTINCT
AssetId,
dbo.fnMyFunction(AssetId)
FROM Assets
which would give these results for the same dataset above (with just one row for AssetId = 5):
/------------------------\
| AssetId | AssetIdPlus1 |
|---------+--------------|
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
| 5 | 6 |
| 7 | 8 |
\------------------------/

Convert Decimal to String on Pivot

example Code
Declare
#table1 VARCHAR(MAX)
Set #table1 = 'Select * from #tempTbl'
Declare
#List VARCHAR(MAX),
#Pivot VARCHAR(MAX)
Select #List = ISNULL(#List + ',', '') + TrxCd From TransacMaster Where Module = 'CB'
Set #Pivot = '
SELECT ROW_NUMBER() OVER (ORDER BY DebtorCd ASC) As RowIndex, *
FROM (
Select Distinct
c.UserId,
d.Name,
b.TrxCd
SUM(b.Amount) As Amount
From tbl_InvH a
Inner Join tbl_InvD b on a.subCd = b.subCd and a.InvNo = b.InvNo
Left Join tbl_User c On a.UserId = c.UserId
Left Join tbl_Personnel d on c.PersonnelId = d.PersonnelId
Group By c.UserId, d.Name, b.TrxCd
) as s
PIVOT
(
SUM(Amount)
FOR TrxCd IN (' + #List + ')
)AS pvt'
Declare #Result nVarchar(MAX)
Set #Result = #table1 + '
Union All
' + #Pivot
Exec sp_executesql #Result
I want to Convert Field Amount from decimal to String, because after this I want to UNION with another tables, but field amount and field from another table is different type.
I have tried CAST(SUM(Amount) as Varchar) But Error :
'CAST' is not a recognized aggregate function.
I can't Convert on Main Select because Field of TrxCd is Dynamic
Result Of Pivot
RowIndex | UserId | Name | IT01 | IT02 | IT03 | IT04
--------------------------------------------------------------------------------
1 | John | John Ivy | 2,000 | 2,000 | 1,000 | 5,000
2 | Merry | Merry Ish | 1,000 | 1,000 | 1,000 | 6,000
other Table
RowIndex | UserId | Name | Transac1 | Transac2 | Transac3 | Transac4
-------------------------------------------------------------------------------------------------
1 | John | John Ivy | Trx Bank A | Trx Bank B | Trx Bank C | Trx Bank D
What should I do to Convert Field Amount from Pivot.
Because of the dynamic nature, you could take the same #List expression Select #List = ISNULL(#List + ',', '') + TrxCd From TransacMaster Where Module = 'CB' and create a second for the dynamic casting in the main select;
Select #List2 = ISNULL(#List2 + ',', '') + 'cast(' + TrxCd + 'as varchar)' From TransacMaster Where Module = 'CB'
Then use this and additional columns required to replace the asterix in the main select;
'SELECT ROW_NUMBER() OVER (ORDER BY DebtorCd ASC) As RowIndex, UserId, Name,' + #List2 +'....'

Dynamically create columns in SQL select query and join tables

I have 2 tables. They are as follows
Table : Grade
GradeID | Grade
-----------------
1 | Chopsaw
2 | Classic
3 | Chieve
Table : Moulded Quantity
Batch ID | Grade | Moulded | Date
-------------------------------------
1 | 1 | 150 | 21st May
2 | 1 | 150 | 22nd May
3 | 2 | 150 | 21st May
4 | 2 | 150 | 21st May
5 | 2 | 150 | 22nd May
I should get the Output like the following
Date | Moulded | Chopsaw | Classic | Cieve
--------------------------------------------------
21st May | 450 | 150 | 300 | 0
22nd May | 300 | 150 | 150 | 0
I am using MSSQL 2008 and i use Crystal report to display the same.
If the number of grades is known beforehand then you can do it with a static query.
SELECT date,
SUM(moulded) moulded,
SUM(CASE WHEN grade = 1 THEN moulded ELSE 0 END) Chopsaw,
SUM(CASE WHEN grade = 2 THEN moulded ELSE 0 END) Classic,
SUM(CASE WHEN grade = 3 THEN moulded ELSE 0 END) Chieve
FROM moulded_quantity
GROUP BY date
This query is not vendor specific so it should work on any major RDBMS.
Now, if the number of grades is unknown or you want it to work even if you make changes to grade table (without changing the query itself) you can resort to dynamic query. But dynamic SQL is vendor specific. Here is an example of how you can do that in MySql
SELECT CONCAT (
'SELECT date, SUM(moulded) moulded,',
GROUP_CONCAT(DISTINCT
CONCAT('SUM(CASE WHEN grade = ',gradeid,
' THEN moulded ELSE 0 END) ', grade)),
' FROM moulded_quantity GROUP BY date') INTO #sql
FROM grade;
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Output (in both cases):
| DATE | MOULDED | CHOPSAW | CLASSIC | CHIEVE |
---------------------------------------------------
| 21st May | 450 | 150 | 300 | 0 |
| 22nd May | 300 | 150 | 150 | 0 |
Here is SQLFiddle demo (for both approaches).
UPDATE In Sql Server you can use STUFF and PIVOT to produce expected result with dynamic sql
DECLARE #colx NVARCHAR(MAX), #colp NVARCHAR(MAX), #sql NVARCHAR(MAX)
SET #colx = STUFF((SELECT ', ISNULL(' + QUOTENAME(Grade) + ',0) ' + QUOTENAME(Grade)
FROM grade
ORDER BY GradeID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #colp = STUFF((SELECT DISTINCT ',' + QUOTENAME(Grade)
FROM grade
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #sql = 'SELECT date, total moulded, ' + #colx +
' FROM
(
SELECT date, g.grade gradename, moulded,
SUM(moulded) OVER (PARTITION BY date) total
FROM moulded_quantity q JOIN grade g
ON q.grade = g.gradeid
) x
PIVOT
(
SUM(moulded) FOR gradename IN (' + #colp + ')
) p
ORDER BY date'
EXECUTE(#sql)
Output is the same as in MySql case.
Here is SQLFiddle demo.
I would suggest you before asking any question research first as it is very common question.
Updated
DECLARE #COLUMNS varchar(max)
SELECT #COLUMNS = COALESCE(#COLUMNS+'],[' ,'') + CAST(Grade as varchar)
FROM Grade
GROUP BY Grade
SET #COLUMNS = '[' + #COLUMNS + ']'
DECLARE #COLUMNS_WITH_NULL varchar(max)
SELECT #COLUMNS_WITH_NULL = COALESCE(#COLUMNS_WITH_NULL+',ISNULL([' ,'ISNULL([') + CAST(Grade as varchar) + '], 0) AS ' + CAST(Grade as varchar)
FROM Grade
GROUP BY Grade
DECLARE #COLUMNS_SUMS varchar(max)
SELECT #COLUMNS_SUMS = COALESCE(#COLUMNS_SUMS+' + ISNULL([' ,'ISNULL([') + CAST(Grade as varchar) + '], 0) '
FROM Grade
GROUP BY Grade
SET #COLUMNS_SUMS = '(' + #COLUMNS_SUMS + ') as Moulded'
PRINT #COLUMNS_SUMS
EXECUTE (
'
SELECT
Date, ' + #COLUMNS_SUMS + ', ' + #COLUMNS_WITH_NULL + '
FROM (
SELECT
m.Moulded,
m.date AS Date,
g.Grade
FROM Grade g
INNER JOIN [Moulded Quantity] m
ON m.GRADE = g.GradeID
) up
PIVOT (SUM(Moulded) FOR Grade IN ('+ #COLUMNS +')) AS pvt')