Query results as comma-delimited string without using PIVOT? - c#

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 |

Related

Remove need for second T-SQL query

I am loading some data into a repeater which is coming from two tables. The query against the second table is only selecting the MAX record though, and because of this complexity, I'm having to create a child repeater to then go off and find the Max record to display.
Table A: Activity List
ID | Activity
----+-----------------------
1 | Change Oil Filter
2 | Change brake fluid
3 | Change brake rotors
Table B: Mechanics Log
ID | ActivityID | Date | Mechanic | Comment
---+-------------+-------------+-------------------------------------------
1 | 1 | 2019-27-06 | John | Changed the oil filter
2 | 1 | 2019-26-06 | Sally | No oil filters in stock.
3 | 2 | 2019-20-06 | Sally | Brake fluid flushed.
As stated above, I can produce the following table using two repeaters (one inside the other) and it looks like this.
ActivityID | Date | Mechanic | Comment
-------------+-------------+-----------------------------------------
1 | 2019-27-06 | John | Changed the oil filter
2 | 2019-20-06 | Sally | Brake fluid flushed.
3 | | |
My question is: How can I produce the same table but using only one repeater and 1 T-SQL query? Is it possible? The reason being is that this is a very simple list (shortened for this demonstration) of the full list I have to enable for my mechanics work log, and when i start going to 100+ activities that can be done on a vehicle, the page loads quite slow; assuming because it has to fire off the 2nd repeater + code for each record it has bound.
I also apologize I do not yet have a 'starting point' for you to work with, as nothing I have created has come even close to producing the result in one query. I am having trouble working out how I combine the first part of the query with the MAX(Date) of the 2nd table. Hoping for some assistance from the community to help.
You can use the below query to get the desired result -
Sample Data
Declare #ActivityList Table
(ID int, Activity varchar(100))
Insert into #ActivityList
values
(1 , 'Change Oil Filter' ),
(2 , 'Change brake fluid' ),
(3 , 'Change brake rotors' )
Declare #MechanicsLog Table
(ID int, ActivityID int, [Date] Date, Mechanic varchar(20), Comment varchar(50))
Insert into #MechanicsLog
values
(1 , 1 , '2019-06-27' , 'John' , 'Changed the oil filter' ),
(2 , 1 , '2019-06-26' , 'Sally' , 'No oil filters in stock.' ),
(3 , 2 , '2019-06-20' , 'Sally' , 'Brake fluid flushed.' )
Query
;With cte as
(select ActivityID, Max([Date]) [date] from #MechanicsLog ml
Group By ActivityID
)
Select al.ID, al.Activity, cte.[Date], Mechanic, Comment
from cte inner join #MechanicsLog ml
on cte.ActivityID = ml.ActivityID and cte.[date] = ml.[Date]
right join #ActivityList al on al.ID = ml.ActivityID
order by ID
If you add use the ROW_NUMBER function to add a sequence to each activity ID, you can then filter that to only get the most recent for each activity ID.
select ActivityID, Date, Mechanic, Comment
from
(
select *, ROW_NUMBER() OVER (PARTITION BY ActivityID order by Date desc) RowNumber
from MechanicsLog
) q1
where RowNumber = 1
This gives you the "MAX" record for each ActivityID but with the rest of the record, so you can join to the Activity List table if you want.
select
act.ActivityID, Max(log.[Date]) as [Date]
from
ActivityList act
inner join
MachineLog log on log.ActivityID = act.ActivityID
Group by
act.ActivityID

How to select multiple Row and multiple field by one code with SQL

I want to select multiple row on a table. But I want to select fields every row too. Here is sample table :
---------------------
OrNo | Name | value
---------------------
1154 | Michael | 41
1154 | Rico | 24
1487 | Alex | 21
1487 | Leo | 27
I want to select based where "Orno" code which in the table is multiple. so I want to get every name and value on 1 of "OrNO".
For an example, I want to select where OrNO 1154. How to select all of name and value from that code? How to used sql data reader for read them?
Edit:
Based answered, I'm sorry, I want to execute on behind code, like sqldatareader with C#/VB.Net. I dont know how to execute them on behind code to store to varriable.
Thank you
SELECT *
FROM MyTable
WHERE OrNo IN
(
SELECT OrNo
FROM
(
SELECT OrNo, COUNT(*) AS RecordCount
FROM MyTable
GROUP BY OrNo
) A
WHERE RecordCount > 1
)
You want to return duplicate records per OrNo, so count per OrNo and only return records with a count > 1.
select orno, name, value
from
(
select orno, name, value, count(*) over (partition by orno) as cnt
from mytable
)
where cnt > 1
order by orno;
It's hard to understand your question.
Are you searching for the SQL Statement? If so, I would suggest:
SELECT *
FROM <TABLE_NAME>
WHERE OrNo IN
(
SELECT OrNo
FROM <TABLE_NAME>
GROUP BY OrNo
HAVING COUNT(*) > 1
)
Sorry, #jmcilhinney was faster here.
And one more, with ties
with t as (
select * from (values
(1154,'Michael',41),
(1154,'Rico',24),
(1199,'Mary',25),
(1487,'Alex',21),
(1487,'Leo',27)) t(OrNo, Name, value )
)
select top(1) with ties OrNo, Name, value
from t
order by
case count(*) over (partition by OrNo ) when 1 then 1 else 0 end

How to use Pivot table for calculating in this scenario?

How to get the below result from the given data.
Report
-------------------------------------------------
ID | Name | Status
-------------------------------------------------
1 | A | Inprogress
2 | A | Inprogress
3 | A | Complete
I need to calculate the result like
---------------------------------------------
Name | Total | Complete | Remaining
---------------------------------------------
A | 3 | 1 | 2
SQL:
Select
[Inprogress], [Complete], [Printed]
from
(select
specimenID, count([RStatus])
from tbl_LabReport
group by specimenID) as sourcetable
Pivot
(Count(specimenID) for [RStatus] in ( [Inprogress],[Complete],[Printed] )) as ptv
You don't need to use PIVOT operator. Try to use subquery or CROSS APPLY operator to solve your task
;WITH test_data AS(
SELECT 1 AS id, 'A' AS NAME, 'Inprogress' AS [status]
UNION ALL
SELECT 2, 'A', 'Inprogress'
UNION ALL
SELECT 3, 'A', 'Complete'
UNION ALL
SELECT 4, 'B', 'Complete'
)
SELECT DISTINCT
name,
T3.*
FROM test_data AS T
CROSS APPLY (SELECT COUNT(*) AS total,
SUM(CASE WHEN T2.status = 'Complete' THEN 1 ELSE 0 END) AS complete,
SUM(CASE WHEN T2.status = 'Inprogress' THEN 1 ELSE 0 END) AS remaining
FROM test_data AS T2
WHERE T2.name = T.name) AS T3
There are a few approaches you could take. This example uses CASE expressions. If you are not familiar with the concept a CASE allows you to conditional return a selected value. I've converted your sample data into table variable:
Sample Data
/* Creating sample data inside a table variable makes it
* easy to share.
*/
DECLARE #Sample TABLE
(
ID INT,
Name VARCHAR(50),
[Status] VARCHAR(50)
)
;
/* Sample values taken from OP.
*/
INSERT INTO #Sample
(
ID,
Name,
[Status]
)
VALUES
(1, 'A', 'Inprogress'),
(2, 'A', 'Inprogress'),
(3, 'A', 'Complete')
;
The CASE returns a 1 for the required Status and a 0 for everything else. Summing the result provides sub totals.
/* Using CASE to return conditional sub totals.
*/
SELECT
Name,
COUNT([Status]) AS Total,
SUM(CASE WHEN [Status] = 'Complete' THEN 1 ELSE 0 END) AS Complete,
SUM(CASE WHEN [Status] = 'Inprogress' THEN 1 ELSE 0 END) AS Remaining
FROM
#Sample
GROUP BY
Name
;

Is it possible to produce a report matrix as a result set in sql query given a singe database table

Given the following SQL table:
GroupAvailable, GroupAssigned, Title
----------------------------------------
GroupA,GroupA,Widget1
GroupA,GroupB,Widget1
GroupB,GroupA,Widget1
Need a report to look like:
Widget1
GroupA GroupB
GroupA X X
GroupB X
Widget2
etc.
Is this possible to do in query? Or something pretty close? Or would a combination of code and sql be better?
The PIVOT function will get you close to the result:
select name,
coalesce(GroupA, '') GroupA,
coalesce(GroupB, '') GroupB
from
(
select title +' '+ groupavailable name,
groupassigned,
'X' as flag
from yourtable
) d
pivot
(
max(flag)
for groupassigned in (GroupA, GroupB)
) piv;
See SQL Fiddle with Demo.
If you have an unknown number of groups, then you could use dynamic SQL to get the result:
DECLARE #cols AS NVARCHAR(MAX),
#colsNull AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(GroupAvailable)
from yourtable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #colsNull = STUFF((SELECT distinct ', coalesce(' + QUOTENAME(GroupAvailable)+', '''') as '+QUOTENAME(GroupAvailable)
from yourtable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT name,' + #colsNull + '
from
(
select title +'' ''+ groupavailable name,
groupassigned,
''X'' as flag
from yourtable
) x
pivot
(
max(flag)
for groupassigned in (' + #cols + ')
) p '
execute(#query);
See SQL Fiddle with Demo
Both versions will give a result:
| NAME | GROUPA | GROUPB |
------------------------------------
| Widget1 GroupA | X | X |
| Widget1 GroupB | X | |
| Widget2 GroupB | X | |

Dynamically Pivot unknown Data

Trying to pivot dynamic data using LINQ or LAMBDA in C#/MVC4 and have pretty much come to the conclusion that its very difficult to do..
This is basically what I want to do:
I have been able to get this to work with known column names using this example: http://geekswithblogs.net/malisancube/archive/2009/04/21/using-lambda-or-linq-for-pivot-tables.aspx
But I cant find any examples for doing this with dynamic columns.
By dynamic columns I mean that there could be a new row with a different Name and FieldType that has not been in the table before at any time that also needs to be turned into a column.. any pointers?.
I don't know LINQ so I will give you a version that can be used in a SQL Server stored procedure. This type of data transformation is known as a PIVOT. Since you are using SQL Server 2008+, you can use the function.
If you know the values that you want to transform, then you can hard-code the values:
SELECT nodeid, rowid,[FirstName], [LastName], [Title]
FROM
(
SELECT nodeid, rowid, name, value
FROM yourTable
) x
PIVOT
(
max(value)
for name in ([FirstName], [LastName], [Title])
)p
See SQL Fiddle with Demo
Then if you have an unknown number of values, you can implement dynamic SQL:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(name)
from yourtable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT nodeid, rowid,' + #cols + ' from
(
SELECT nodeid, rowid, name, value
FROM yourTable
) x
pivot
(
max(value)
for name in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle with Demo
Both return the results:
| NODEID | ROWID | FIRSTNAME | LASTNAME | TITLE |
--------------------------------------------------
| 1 | 1 | Alfred | Beagle | (null) |
| 1 | 2 | Freddy | (null) | (null) |
| 1 | 3 | (null) | Grey | Sir. |

Categories