C# & SQL Server improvement - c#

I've got multiple selects from C# to one table in SQL Server in one time period through a stored procedure. That's correct, but that's slow and I'd like to improve that, now.
This is my C# code:
while (startDate!= endDate)
{
var anyDay_CntPost = 0;
anyDay_CntPost = db.GetPostCount(1, tmpDate).Select(x => x.cntPost).FirstOrDefault().Value;
if (anyDay_CntPost != 0)
{
var anyDay_cnt1 = db.GetPostCount(1, tmpDate).Select(x => x.cntPost).FirstOrDefault().Value; ;
var anyDay_cnt2 = db.GetPostCount(2, tmpDate).Select(x => x.cntPost).FirstOrDefault().Value;
var anyDay_cnt3 = db.GetPostCount(3, tmpDate).Select(x => x.cntPost).FirstOrDefault().Value;
listCount.arr1.Add(anyDay_cnt1);
listCount.arr2.Add(anyDay_cnt2);
listCount.arr3.Add(anyDay_cnt3);
}
startDate = startDate.AddDays(1);
}
And this is the stored procedure code:
ALTER PROCEDURE [dbo].[GetPostCount]
#type int,
#date nvarchar(max)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
----<<-----------------------------
if #type = 1
begin
SELECT cntPost = count(*)
FROM Post
WHERE Date = #date AND type = 1
end
---<<------------------------------
if #type = 1
begin
SELECT cntPost = count(*)
FROM Post
WHERE Date = #date and type = 2
end
---<<------------------------------
if #type = 2
begin
SELECT cntPost = count(*)
FROM Post
WHERE Date = #date and type = 3
end
End
My result is:
____________________________________________
| Date | Count 1 | Count 2 | Count 3 |
------------------------------------------
| 10/25/2015 | 200 | 360 | 547 |
| 10/24/2015 | 185 | 326 | 132 |
| 10/23/2015 | 100 | 490 | 670 |
------------------------------------------
I want optimize the above code, because it's too slow and tardy. What is your suggestion?

My solution would be the following procedure:
create procedure [dbo].[GetPostCount]
#startdate date,
#enddate date
as
select Date, Type, count(*) as cntPost
from Post
where Date >= #startdate and Date <= #enddate and Type in (1, 2, 3)
group by Date, Type
You just select all data that you need once and then use it in your while loop. Now you are querying database 4 times in each iteration and of course it is slow.

Related

Select Data with Column's Description not null, and then replace column name with description

I have a table 'PurchaseOrder'. I want select data when column's description is not null. and then replace the column's name with it's description.
table PurchaseOrder
ID | Product | Use | Price | Comment
-----------------------------------------------------
1 | Cellphone | true | 100 |
2 | Car | false | 10 |
3 | Table | true | 200 |
Column
Name | Description
---------------------------
ID | Index
Produce | Name
Use |
Price | Sale
Comment |
The Select result will be
Index | Name | Sale
--------------------------------
1 | Cellphone | 100
2 | Car | 10
3 | Table | 200
Now, I just get the column with description
if object_id('tempdb..#dt') is not null drop table #dt
select
sc.column_id [Position],
sc.name [Column],
sc.max_length [Length],
sep.value [Description]
into #dt
from sys.tables st
inner join sys.columns sc on st.object_id = sc.object_id
left join sys.extended_properties sep on st.object_id = sep.major_id
and sc.column_id = sep.minor_id
and sep.name = 'MS_Description'
where st.name = 'PurchaseOrder' and sep.value is not null
How to generate the final data table?
DECLARE
#TABLE_NAME NVARCHAR(50) = 'PurchaseOrderDetail',
#TABLE_SCHEMA Nvarchar(50) = 'Purchasing',
#COL_LIST NVARCHAR(MAX),
#SQL NVARCHAR(4000),
#COL NVARCHAR(500)
DECLARE c_cursor CURSOR FOR
SELECT sc.name + ' as ' + QUOTENAME(CAST(sep.value AS varchar)) AS Expr1
FROM sys.tables AS st INNER JOIN
sys.columns AS sc ON st.object_id = sc.object_id INNER JOIN
sys.extended_properties AS sep ON st.object_id = sep.major_id AND sc.column_id = sep.minor_id AND sep.name = 'MS_Description'
WHERE st.name = #TABLE_NAME AND sep.value IS NOT NULL
OPEN c_cursor;
FETCH NEXT
FROM c_cursor INTO #COL;
WHILE ( ##FETCH_STATUS = 0 )
BEGIN
SELECT #COL_LIST = COALESCE(#COL_LIST+',' ,'') + #COL
FETCH NEXT FROM c_cursor
INTO #col;
END CLOSE c_cursor;
DEALLOCATE c_cursor;
SET #SQL = ' SELECT ' + #COL_LIST +' FROM ' + QUOTENAME(#TABLE_SCHEMA)+'.'+QUOTENAME(#TABLE_NAME)
PRINT #SQL;
EXEC (#sql);

Count Consecutive vacation days skip through holidays and weekends

I have a table which has records of user's vacation days.
A Sample of that would be:
+---------+-----------+---------+------------+
| country | user_name | user_id | vac_date |
+---------+-----------+---------+------------+
| canada | James | 1111 | 2015-02-13 |
| canada | James | 1111 | 2015-02-17 |
| canada | James | 1111 | 2015-02-18 |
| canada | James | 1111 | 2015-02-10 |
| canada | James | 1111 | 2015-02-11 |
+---------+-----------+---------+------------+
With the above data, the count would be 3 from feb 13th to feb 18th, because 14th and 15th are weekends and the 16th is a holiday here in Canada. So essentially, I am trying to hold and continue the count if the user took the next working day off. I also have a table that has all the holidays which includes the country and the date of the holiday. Sample data for the holiday table would be:
+---------+-------------+-------------+
| country | holidayDesc | holidayDate |
+---------+-------------+-------------+
| canada | Family Day | 2015-02-16 |
+---------+-------------+-------------+
Currently i have a query in SQL that counts the the dates normally, so it only counts whatever is in the vacation table. For example: if a user took march 3rd 2015, march 4th 2015, and march 5th 2015 off, then it will have a count of 3, but for that above table example, it would only have a count of 1 for feb 13th and 2 from feb 17th to feb 18th.
SELECT DISTINCT user_name
,min(vac_date) as startDate
,max(vac_date) as endDate
,datediff(day, min(vac_date), max(vac_date)) as consecutiveCount
FROM (
SELECT user_name
,vac_date
,user_id
,groupDate = DATEADD(DAY, - ROW_NUMBER() OVER (
PARTITION BY user_id ORDER BY vac_date
), vac_date)
FROM mytable
WHERE country = 'canada'
AND vac_date BETWEEN '20150101'
AND '20151231'
) z
GROUP BY user_name
,groupDate
HAVING datediff(day, min(vac_date), max(vac_date)) >= 0
ORDER BY user_name
,min(vac_date);
This is what it currently outputs from the above sample data:
+-----------+------------+------------+------------------+
| user_name | startDate | endDate | consecutiveCount |
+-----------+------------+------------+------------------+
| James | 2015-02-10 | 2015-02-11 | 2 |
| James | 2015-02-13 | 2015-02-13 | 1 |
| James | 2015-02-17 | 2015-02-18 | 2 |
+-----------+------------+------------+------------------+
Ideally i would like it to be:
+-----------+------------+------------+------------------+
| user_name | startDate | endDate | consecutiveCount |
+-----------+------------+------------+------------------+
| James | 2015-02-10 | 2015-02-11 | 2 |
| James | 2015-02-13 | 2015-02-18 | 3 |
+-----------+------------+------------+------------------+
But i don't know if that is possible with pure SQL. I can also try to incorporate it into C#.
If it helps I am also using C# and SQL Server Management Studio. Any help would be appreciated. Thanks in advance
I try to go a different route, but then found the fix for John Cappelletti solution.
First you need to add weekend dates to your holiday table.
Get a list of dates between two dates using a function
Then UNION ALL vacation days with holidays, but add a description field so you can difference between both.
There are some CROSS JOIN so you can have holiday and weekends for each country and user (need testing)
SELECT [country],
[user_name], [user_id], [vac_date], 'vacation' as description
FROM vacations
UNION ALL
SELECT c.[country],
u.[user_name],
u.[user_id],
[holidayDate],
'holiday' as description
FROM holidays
CROSS JOIN (SELECT DISTINCT [country] FROM vacations) c
CROSS JOIN (SELECT DISTINCT [user_name], [user_id] FROM vacations) u
Then the final query is the same as John suggested, but this time you only count vacation days.
WITH joinDates as (
SELECT [country],
[user_name], [user_id], [vac_date], 'vacation' as description
FROM vacations
UNION ALL
SELECT c.[country],
u.[user_name],
u.[user_id],
[holidayDate],
'holiday' as description
FROM holidays
CROSS JOIN (SELECT DISTINCT [country] FROM vacations) c
CROSS JOIN (SELECT DISTINCT [user_name], [user_id] FROM vacations) u
)
Select user_name
,startDate = min(vac_date)
,endDate = max(vac_date)
,consecutiveCount = count(*)
From (
Select *
,Grp = Day(vac_date) - Row_Number() over (Partition By country,user_id
Order by vac_date)
From joinDates S
) A
WHERE description = 'vacation' -- only count vacation days ignore holiday/weekend
Group By user_name, Grp
Having count(*)>1
ORDER BY startDate
SQL DEMO
OUTPUT
RAW OUTPUT
here you can see the data before the group by
This seems like a classic Gaps & Islands with a little twist.
Declare #YourTable table (country varchar(25),user_name varchar(25),user_id varchar(25),vac_date date)
Insert Into #YourTable values
('canada','James','1111','2015-02-13'),
('canada','James','1111','2015-02-17'),
('canada','James','1111','2015-02-18'),
('canada','James','1111','2015-02-10'),
('canada','James','1111','2015-02-11')
Declare #Holiday table (country varchar(25),holidayDate date)
Insert Into #Holiday values
('canada','2015-02-16')
Select user_name
,startDate = min(vac_date)
,endDate = max(vac_date)
,consecutiveCount = sum(DayCnt)
From (
Select *
,Grp = Day(vac_date) - Row_Number() over (Partition By country,user_id Order by vac_date)
From (Select Country,user_name,user_id,vac_date,DayCnt=1 from #YourTable
Union All
Select A.Country,user_name,user_id,vac_date=b.holidayDate,DayCnt=1
From #YourTable A
Join #Holiday B on A.country=B.country and abs(DateDiff(DD,vac_date,holidayDate))=1
Union All
Select A.Country,user_name,user_id,vac_date=b.retval,DayCnt=0
From #YourTable A
Join (
Select * From [dbo].[udf-Range-Date]('2015-01-01','2017-12-31','DD',1) where DateName(WEEKDAY,RetVal) in ('Saturday','Sunday')
) B on abs(DateDiff(DD,vac_date,RetVal))=1
) S
) A
Group By user_name,Grp
Having Sum(DayCnt)>1
Returns
user_name startDate endDate consecutiveCount
James 2015-02-10 2015-02-11 2
James 2015-02-16 2015-02-18 3
The UDF to generate dynamic Date Ranges -- could be your own query
CREATE FUNCTION [dbo].[udf-Range-Date] (#R1 datetime,#R2 datetime,#Part varchar(10),#Incr int)
Returns Table
Return (
with cte0(M) As (Select 1+Case #Part When 'YY' then DateDiff(YY,#R1,#R2)/#Incr When 'QQ' then DateDiff(QQ,#R1,#R2)/#Incr When 'MM' then DateDiff(MM,#R1,#R2)/#Incr When 'WK' then DateDiff(WK,#R1,#R2)/#Incr When 'DD' then DateDiff(DD,#R1,#R2)/#Incr When 'HH' then DateDiff(HH,#R1,#R2)/#Incr When 'MI' then DateDiff(MI,#R1,#R2)/#Incr When 'SS' then DateDiff(SS,#R1,#R2)/#Incr End),
cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
cte2(N) As (Select Top (Select M from cte0) Row_Number() over (Order By (Select NULL)) From cte1 a, cte1 b, cte1 c, cte1 d, cte1 e, cte1 f, cte1 g, cte1 h ),
cte3(N,D) As (Select 0,#R1 Union All Select N,Case #Part When 'YY' then DateAdd(YY, N*#Incr, #R1) When 'QQ' then DateAdd(QQ, N*#Incr, #R1) When 'MM' then DateAdd(MM, N*#Incr, #R1) When 'WK' then DateAdd(WK, N*#Incr, #R1) When 'DD' then DateAdd(DD, N*#Incr, #R1) When 'HH' then DateAdd(HH, N*#Incr, #R1) When 'MI' then DateAdd(MI, N*#Incr, #R1) When 'SS' then DateAdd(SS, N*#Incr, #R1) End From cte2 )
Select RetSeq = N+1
,RetVal = D
From cte3,cte0
Where D<=#R2
)
/*
Max 100 million observations -- Date Parts YY QQ MM WK DD HH MI SS
Syntax:
Select * from [dbo].[udf-Range-Date]('2016-10-01','2020-10-01','YY',1)
Select * from [dbo].[udf-Range-Date]('2016-01-01','2017-01-01','MM',1)
*/
OK, my understanding of the question is that what you want to do is count spans of days off as only one day. Many businesses call this an "occurrence of absence" to differentiate absences by cause. In this case, you're trying to treat holidays as a continuance of the holiday (for time purposes) and if a holiday occurs on a Friday but the person takes Monday off, that should be one contiguous time out.
Personally, I'd do this in C# because of properties of the DateTime object that could make this a lot easier than trying to make a frankenquery. The code below assumes that you have an object called an Employee that contains its own record of DateTimes, like so:
public class Employee
{
public int ID {get;set;}
public string Name {get;set;}
public List<DateTime> DaysIWasOut {get;set;}
}
public static int TimeOut(IEnumerable employees)
{
int totalOutInstances = 0;
DataTable dt = HolidaysPlease(); //this refers to another method
//to fill the table. Just a basic SQLAdapter.Fill kind of thing.
//Basic so I won't waste time on it here.
foreach(var e in employees)
{
var holidays = dt.AsEnumerable().Where(t => Convert.ToDateTime(t[3]) == d) //holidays now has all of the holidays the employee had off.
totalOutInstances = e.DaysIWasOut.Count();
foreach(var d in e.DaysIWasOut)
{
int daystolook = 0;
if (d.DayOfWeek == DayOfWeek.Friday)
daystolook +=3;
else
daystolook +=1;
if(e.DaysIWasOut.Contains(d.AddDays(daystolook))
{totalOutInstances --; } //don't count that day
}
}
return totalOutInstances;
}

What causes the "Subquery returns more than 1 row" error?

I'm trying to add a new Back Order to the Back Order table in my MYSQL database. The problem I'm getting is that when I try to select the Supplier_ID to add it to the Back Order Table, the program gives me an error that says "Subquery returns more than 1 value".
Supplier Table (Unsure how to properly structure it)
| Supplier_ID | SupName |
| 1| EWS |
| 6 | Franklin Bakery |
Back Order Table
| BackOr_ID | Supplier_ID | BackOr_Org_Date | Sup_Name |
The MYSQL query I'm currently using is:
CREATE DEFINER=`root`#`%` PROCEDURE `sp_BackOrder`(
in supname varchar(50),
in dat date
)
BEGIN
insert into Back_Order
(
Supplier_ID,
BackOr_Org_Date,
Sup_Name
)
values
(
(select Supplier_ID from Supplier Where SupName = supname),
dat,
supname
);
END
The C# Code that uses the query is:
MySqlCommand cmd = new MySqlCommand("sp_BackOrder", new MySqlConnection(*Connection String*));
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new MySqlParameter("supname", Supp_Name)); //Supp_Name is the Supplier Name (a string variable)
cmd.Parameters.Add(new MySqlParameter("dat", DateTime.Now.ToShortDateString())); //dat is the date the Order is placed
cmd.Connection.Open();
cmd.ExecuteNonQuery();
cmd.Connection.Close();
The only error I get is that the Subquery (Which I assume is the Select Query) returns more than 1 value. I've tried looking around and even looked on Stackoverflow but couldn't find any solution to the problem. Any help would be appreciated.
It would need to look like:
delimiter $$
CREATE DEFINER=`root`#`%` PROCEDURE `sp_BackOrder`
( in p_supname varchar(50),
in p_dat date
)
BEGIN
insert into Back_Order(Supplier_ID, BackOr_Org_Date, Sup_Name)
select Supplier_ID, p_dat, p_supname from Supplier Where SupName = p_supname;
END$$
delimiter ;
or
CREATE DEFINER=`root`#`%` PROCEDURE `sp_BackOrder`
( in p_supname varchar(50),
in p_dat date
)
BEGIN
insert into Back_Order(Supplier_ID, BackOr_Org_Date, Sup_Name)
select Supplier_ID, p_dat, p_supname from Supplier Where SupName = p_supname;
END
Same deal in both just depending on your DELIMITER needs.
The parameter name supname of procedure and column name SupName are same. Change parameter name to something other than column name.
CREATE DEFINER=`root`#`%` PROCEDURE `sp_BackOrder`(
in selectedSupname varchar(50),
in dat date
)
BEGIN
insert into Back_Order
(
Supplier_ID,
BackOr_Org_Date,
Sup_Name
)
values
(
(select Supplier_ID from Supplier Where SupName = selectedSupname),
dat,
selectedSupname
);
END

SQL Multiple Date Column, Value Bucket

Please help with this SQL Table Query, I Have a Table Like
+---------------------------------------------+
| DateCol1 DateCol2 DateCol3 DateCol4 |
+---------------------------------------------+
| 2014-10-01 null null 2014_10_04 |
| 2014_10_02 2014_10_01 null 2014_10_04 |
| 2014_10_02 null 2014_10_01 2014_10_04 |
| 2014_10_02 null 2014_10_01 null |
+---------------------------------------------+
If the user is giving input like FromDate = '2014-10-01' and ToDate = '2014-10=05'
I have To Show Like
+------------------------------------------------------------------+
| ActivityDate DateCol1_Cnt DateCol2_Cnt DateCol3_Cnt DateCol4_Cnt |
+------------------------------------------------------------------+
| 2014-10-01 1 1 2 0 |
| 2014-10-02 3 0 0 0 |
| 2014-10-03 0 0 0 0 |
| 2014-10-04 0 0 0 3 |
+------------------------------------------------------------------+
what i have to show is number of activity in a Particluar date
what i did so far is
Select 'Date1_ACty' Activity ,dateColumn1 Activity_Date, Count(1) Activity_count
From MyTable where dateColumn1 between #FromDate and #ToDate
union all
Select 'Date2_ACty' Activity ,dateColumn2 Activity_Date, Count(1) Activity_count
From MyTable where dateColumn2 between #FromDate and #ToDate
union all .....
So Far For Remaining column
Please help me with good solution
Problem is I am Getting DateCol_Acty, DateCo2_Acty etc as column values not as column itself :(
Maybe doing anUNPIVOTfollowed by a newPIVOTwould work? It's not beautiful, but it seems to get the correct results I think, except for missing the empty dates, but that could be fixed by left joining a column with all dates in the range.
SQL Fiddle
MS SQL Server 2012 Schema Setup:
create table t (id int, DateCol1 date, DateCol2 date, DateCol3 date, DateCol4 date);
insert t values
(1, '2014-10-01', null, null, '2014-10-04'),
(2, '2014-10-02', '2014-10-01', null, '2014-10-04'),
(3, '2014-10-02', null, '2014-10-01', '2014-10-04'),
(4, '2014-10-02', null, '2014-10-01', null);
Query 1:
DECLARE #FromDate date = '2014-10-01', #ToDate date = '2014-10-05'
SELECT
ActivityDate,
DateCol1 AS DateCol1_Cnt,
DateCol2 AS DateCol2_Cnt,
DateCol3 AS DateCol3_Cnt,
DateCol4 AS DateCol4_Cnt
FROM (
SELECT d, Dates AS ActivityDate, dates as d2
FROM (SELECT DateCol1, DateCol2, DateCol3, DateCol4 FROM t) AS p
UNPIVOT (Dates FOR d IN (DateCol1, DateCol2, DateCol3, DateCol4)) AS unpvt
) derived
PIVOT (COUNT(d2) FOR d IN (DateCol1, DateCol2, DateCol3, DateCol4)) pvt
WHERE ActivityDate BETWEEN #FromDate AND #ToDate
Results:
| ACTIVITYDATE | DATECOL1_CNT | DATECOL2_CNT | DATECOL3_CNT | DATECOL4_CNT |
|--------------|--------------|--------------|--------------|--------------|
| 2014-10-01 | 1 | 1 | 2 | 0 |
| 2014-10-02 | 3 | 0 | 0 | 0 |
| 2014-10-04 | 0 | 0 | 0 | 3 |
Is something like this what you are looking for?
declare #table table(id int, date1 date, date2 date, date3 date, date4 date)
declare #min date = '2014-10-01', #max date = '2014-10-04';
insert into #table
values
(1, '2014-10-01', null, null, '2014-10-04'),
(2, '2014-10-02', '2014-10-01', null, '2014-10-04'),
(3, '2014-10-02', null, '2014-10-01', '2014-10-04'),
(4, '2014-10-02', null, '2014-10-01', null);
with date1
as (
select date1 date_,
count(*) count_
from #table
where date1 between #min
and #max
group by date1
),
date2
as (
select date2 date_,
count(*) count_
from #table
where date2 between #min
and #max
group by date2
),
date3
as (
select date3 date_,
count(*) count_
from #table
where date3 between #min
and #max
group by date3
),
date4
as (
select date4 date_,
count(*) count_
from #table
where date4 between #min
and #max
group by date4
),
dates
as (
select #min date_
union all
select dateadd(day, 1, date_)
from dates
where dateadd(day, 1, date_) <= #max
)
select d.date_,
ISNULL(d1.count_, 0) DateCol1_Cnt,
ISNULL(d2.count_, 0) DateCol2_Cnt,
ISNULL(d3.count_, 0) DateCol3_Cnt,
ISNULL(d4.count_, 0) DateCol4_Cnt
from dates d
left join date1 d1 on d1.date_ = d.date_
left join date2 d2 on d2.date_ = d.date_
left join date3 d3 on d3.date_ = d.date_
left join date4 d4 on d4.date_ = d.date_;

Query results as comma-delimited string without using PIVOT?

i want to create a query from multiple records as one record , but i don't want to use Pivot, FYI , i have > 260 Records , it is impossible if i Write Manual PIVOT,
is there any Simple solutions?
here's the table Example :
ID Element_Name Value
1 Parmitha 100
2 Anggun 200
3 Chandra 300
4 BagusofTerror 400
5 Laras 500
6 Jessica 600
7 Aisyah 700
......
200 Sonya 20000
and i want the result is like this :
paramitha , anggun, chandra , bagusofterror, Laras , Jessica , Aisyah, ..... , Sonya
100 , 200, 300, 400,500,600,700,....,20000
In reference to http://blog.sqlauthority.com/2009/12/21/sql-server-comma-separated-values-csv-from-table-column-part-2/ you could use the following SQL query
I havent run this, so I'm not 100% sure it'll work
SELECT STUFF(
(SELECT ',' + s.ElementName
FROM tableName s
FOR XML PATH('')),1,1,'')
UNION ALL
SELECT STUFF(
(SELECT ',' + s.Value
FROM tableName s
FOR XML PATH('')),1,1,'')
We used to call this a cross-tab query. Not sure if it still is...
SELECT SUM(CASE WHEN id=1 THEN value ELSE 0 END) AS parmitha,
SUM(CASE WHEN id=2 THEN value ELSE 0 END) AS anggun,
SUM(CASE WHEN id=3 THEN value ELSE 0 END) AS chandra,
...etc...
SUM(value) AS total
FROM My_Table
WHERE ...etc...
I don't know c#, but I'm sure you can get it to loop over the column to prepare the SUM().
How about this that I tried on the sample dataset you provided.
declare #intFlag int
Declare #AnsString nvarchar(2000)
SET #intFlag=1
SET #AnsString=''
While (#intFlag<=200)
Begin
Select #AnsString=#AnsString
+CONVERT(Varchar(20),(SELECT [Element_Name]
FROM TABLE where RowID=#intFlag))
+', '
SET #intFlag=#intFlag+1
if #intFlag=199
break;
END
Print #AnsString
--Select #AnsSTring
If you want this data in separate columns, then you can use dynamic SQL to PIVOT the data in SQL Server 2005+. Your code would be similar to this:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(element_name)
from yourtable
group by element_name, id
order by id
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query
= 'select '+#cols+'
from
(
select Element_name, Value
from yourtable
) p
pivot
(
max(value)
for Element_name in('+#cols+')
) piv'
execute(#query)
See SQL Fiddle with Demo. This gives the result:
| PARMITHA | ANGGUN | CHANDRA | BAGUSOFTERROR | LARAS | JESSICA | AISYAH | SONYA |
----------------------------------------------------------------------------------
| 100 | 200 | 300 | 400 | 500 | 600 | 700 | 20000 |

Categories