SQL order by hierachical like - sql

I'm using a Confluence Web page, which display a dropdown list based on a database function. This function have no parameter. This function returns results of a view.
When I begin to entered some text on the textfield, the dropdown list result show data sort.
By instance:
text entered : toto
dropdown list list result :
aaa.toto.aim
aaa.toto.becare
toto
toto.aim
toto.aim.thisis
toto.becare
toto.becare.xxx
the view has multiple columns : code_part1, code_part2, code_part3, fullcode (correspond to result display, concatenation of code_part1 + '.' + code_part2 + '.' + code_part3 ) :
fullcode | code_part1 | code_part2 | code_part3
aaa.toto.aim | aaa | toto | aim
aaa.toto.becare | aaa | toto | becare
toto | toto | (null) | (null)
toto.aim | toto | aim | (null)
toto.aim.thisis | toto | aim | thisis
toto.becare | toto | becare | (null)
toto.becare.xxx | toto | becare | xxx
How it's possible update the function with the order by clause depending on what I entered on text box ("toto" here) :
toto
toto.aim
toto.aim.thisis
toto.becare
toto.becare.xxx
aaa.toto.aim
aaa.toto.becare

you can make use of case in order by
DECLARE #SearchString CHAR ='toto'
SELECT fullcode
FROM TABLENAME
ORDER BY CASE WHEN part1 = #SearchString THEN part1 WHEN part2 = #SearchString THEN PART2 ELSE part3 END

try this,
declare #t table(fullcode varchar(50),code_part1 varchar(50), code_part2 varchar(50), code_part3 varchar(50))
insert INTO #t VALUES
('aaa.toto.aim' ,'aaa' , 'toto' , 'aim' )
,('aaa.toto.becare' ,'aaa' , 'toto' , 'becare' )
,('toto' ,'toto' , null , null )
,('toto.aim' ,'toto' , 'aim' , null )
,('toto.aim.thisis' ,'toto' , 'aim' , 'thisis' )
,('toto.becare' ,'toto' , 'becare' , null )
,('toto.becare.xxx' ,'toto' , 'becare', 'xxx' )
declare #key varchar(50)='toto'
select *,1 rownum from #t where code_part1=#key
union ALL
select *,2 rownum from #t where code_part2=#key
union ALL
select *,3 rownum from #t where code_part3=#key

Related

SSIS - Concatenating and Lookups to create a string

I am trying to combine many columns together to create a full string.
This is what I mean:
I have a table named QRFormats that looks like this:
| Id | Text1 | Variable1 | Text2 | Variable2 | Text3 | Variable3 |
| 1 | The Color | Color | Is designated | Description | *NULL* | *NULL* |
| 2 | The Company | Company| Is Located | Location| In Country | Country|
| 3 | The Part is | PartNumber| Work Order:| WorkOrder| *NULL* | CompanyCode |
.
.
The complete string should print the Text and lookup the Variable in completely different table using FK/PK correlations.
All the Variables are located in two possible tables called PartData and Company
PartData
| Id | PartNumber | Color | WorkOrder | Description |
| 1 | 123456789 | Blue | 111222333 | Microchip |
| 2 | 101441414 | Silver | 55556666 | Handel |
Company
| Id | Company | Location | CompanyCode | Country |
| 1 | Microsoft | Seattle | 1234 | USA |
| 2 | Apple | California | 1122 | USA |
.
Some Examples of what I am trying to do....
.
The Complete string should look as follows if my:
-QRFormats FK is a 1:
-PartDataFK is a 1:
-Company FK is a 1:
"The Color Blue Is designated Microchip"
.
The Complete string should look as follows if my:
-QRFormats FK is a 2:
-PartDataFK is a 1:
-Company FK is a 3:
"The Company Apple Is Located California In Country USA"
.
The Complete string should look as follows if my:
-QRFormats FK is a 3:
-PartDataFK is a 2:
-Company FK is a 1:
"The Part is 101441414 WorkOrder: 555566661234"
.
Thank you very much for you help, I am using SSIS in VisualStudio 2015.
This is a very interesting request. First the DML:
create table #QFR
(
Id int
, Text1 varchar(100)
, Variable1 varchar(100)
, Text2 varchar(100)
, Variable2 varchar(100)
, Text3 varchar(100)
, Variable3 varchar(100)
)
insert into #QFR
values
( 1,' The Color ','Color',' Is designated ','Description ',NULL ,NULL )
,( 2,' The Company ','Company',' Is Located ','Location',' In Country ','Country' )
,( 3,' The Part is ','PartNumber','Work Order:','WorkOrder',NULL ,'CompanyCode' )
create table #parts
(
Id int
, PartNumber varchar(100)
, Color varchar(100)
, WorkOrder varchar(100)
, Description varchar(100)
)
insert into #parts
values
(1,'123456789','Blue ','111222333',' Microchip '),
(2,'101441414','Silver ','55556666',' Handel ')
create table #company
(
Id int
, Company varchar(100),
Location varchar(100)
, CompanyCode varchar(100)
, Country varchar(100)
)
insert into #company
values
(1,' Microsoft ','Seattle ','1234',' USA ')
,(2,' Apple ','California ','1122',' USA ')
I create a CTE to flip the variable logic on its side and joined it in several times to make this work...
declare #qID int = 1
,#pID int = 1
,#cID int = 1
;with cte as
(
select Label,Value
from #parts
cross apply (values('PartNumber',PartNumber),('Color',Color),('WorkOrder',WorkOrder),('Description',Description)) as a(Label,Value)
where id =#pID
union all
select Label,Value
from #company
cross apply (values('Company',Company),('Location',Location),('CompanyCode',CompanyCode),('Country',Country)) as a(Label,Value)
where id =#cID
)
select Text1 , t1.Value , text2 , t2.Value , text3 , t3.Value
from #QFR q
left join cte t1 on q.Variable1=t1.Label
left join cte t2 on t2.Label = q.Variable2
left join cte t3 on t3.label = q.Variable3
where q.id = #qID
Changed to a function:
create function fn_BuildAsentence (#qID int
,#pID int
,#cID int)
returns varchar(max)
as
BEGIN
declare #v varchar(Max)
;with cte as
(
select Label,Value
from parts
cross apply (values('PartNumber',PartNumber),('Color',Color),('WorkOrder',WorkOrder),('Description',Description)) as a(Label,Value)
where id =#pID
union all
select Label,Value
from company
cross apply (values('Company',Company),('Location',Location),('CompanyCode',CompanyCode),('Country',Country)) as a(Label,Value)
where id =#cID
)
select #v = concat(Text1 , t1.Value , text2 , t2.Value , text3 , t3.Value)
from QFR q
left join cte t1 on q.Variable1=t1.Label
left join cte t2 on t2.Label = q.Variable2
left join cte t3 on t3.label = q.Variable3
where q.id = #qID
return #v
END
Finally, I would use a SQL Source (I presume that you are doing this in a data flow to go somewhere)
Select dbo.fn_BuildAsentence(QFR,parts,company),QFR,parts,company
from [whereever]

Splitting dynamically SQL columns into multiple columns based on a different column value

I am trying to convert dynamically a table like this:
+----+---------+-------+
| ID | Subject | Users |
+----+---------+-------+
| 1 | Hi! | Anna |
| 2 | Hi! | Peter |
| 3 | Try | Jan |
| 4 | Try | Peter |
| 5 | Try | Jan |
| 6 | Problem | Anna |
| 7 | Problem | José |
| 8 | Test | John |
| 9 | Test | John |
| 10 | Hi! | Anna |
| 11 | Hi! | José |
| 12 | Hi! | Anna |
| 13 | Hi! | Joe |
+----+---------+-------+
Into something like that:
+----+---------+-------+-------+-------+-------+
| ID | Subject | User1 | User2 | User3 | User4 |
+----+---------+-------+-------+-------+-------+
| 1 | Hi! | Anna | Peter | José | NULL |
| 2 | Try | Jan | Peter | NULL | NULL |
| 3 | Problem | Anna | José | NULL | NULL |
| 4 | Test | John | NULL | NULL | NULL |
+----+---------+-------+-------+-------+-------+
I have been reading the following links, but they are thought for splitting a column into a predefined number of columns:
Splitting SQL Columns into Multiple Columns Based on Specific Column Value
Split column into two columns based on type code in third column
I would need to split it dinamically depending on the content of the table.
SQL:
--【Build Test Data】
create table #Tem_Table ([ID] int,[Subject] nvarchar(20),[Users] nvarchar(20));
insert into #Tem_Table ([ID],[Subject] ,[Users]) values
('1','Hi!','Anna')
,('2','Hi!','Peter')
,('3','Try','Jan')
,('4','Try','Peter')
,('5','Try','Jan')
,('6','Problem','Anna')
,('7','Problem','José')
,('7','Test','John')
,('9','Test','John')
,('10','Hi! ','Anna')
,('11','Hi! ','José')
,('12','Hi! ','Anna')
,('13','Hi! ','Joe')
;
--STEP 1 distinct and ROW_NUMBER
with distinct_table as (
select [Subject],[Users]
,ROW_NUMBER() OVER (PARTITION BY [Subject] order by [Users]) [rank]
from (
select distinct [Subject],[Users] from #Tem_Table
) T00
)
--STEP 2 Group by row_count
,group_table as (
select [Subject]
from distinct_table T
group by [Subject]
)
--STEP 3 Use Left Join and Rank
select
T.[Subject],T1.[Users] as User1, T2.[Users] as User2 , T3.[Users] as User3, T4.[Users] as User4
from group_table T
left join distinct_table T1 on T.[Subject] = T1.[Subject] and T1.[rank] = 1
left join distinct_table T2 on T.[Subject] = T2.[Subject] and T2.[rank] = 2
left join distinct_table T3 on T.[Subject] = T3.[Subject] and T3.[rank] = 3
left join distinct_table T4 on T.[Subject] = T4.[Subject] and T4.[rank] = 4
order by [Subject];
result:
-------------------- -------------------- -------------------- -------------------- --------------------
Hi! Anna Joe José Peter
Problem Anna José NULL NULL
Test John NULL NULL NULL
Try Jan Peter NULL NULL
Update the Dynamic version :
--STEP 1 distinct and ROW_NUMBER
SELECT * into #distinct_table from (
select [Subject],[Users]
,ROW_NUMBER() OVER (PARTITION BY [Subject] order by [Users]) [rank]
from (
select distinct [Subject],[Users] from #Tem_Table
) T00
)T;
--STEP 2 Group by row_count
SELECT * into #group_table from (
select [Subject] ,count(1) [count]
from #distinct_table T
group by [Subject]
)T;
--Use Exec
DECLARE #select_sql AS NVARCHAR(MAX) = ' select T.[Subject] ',
#join_sql AS NVARCHAR(MAX) = ' from #group_table T ',
#max_count INT = (SELECT max([count]) FROM #group_table),
#temp_string NVARCHAR(5),
#temp_string_addone NVARCHAR(5)
;
DECLARE #index int = 0 ;
WHILE #index < #max_count
BEGIN
sELECT #temp_string = Convert(nvarchar(10),#index);
sELECT #temp_string_addone = Convert(nvarchar(10),#index+1);
select #select_sql = #select_sql + ' , T'+#temp_string_addone+'.[Users] as User'+#temp_string_addone+' '
select #join_sql = #join_sql + 'left join #distinct_table T'+#temp_string_addone+' on T.[Subject] = T'+#temp_string_addone+'.[Subject] and T'+#temp_string_addone+'.[rank] = '+#temp_string_addone+' ';
SET #index = #index + 1;
END;
EXEC (#select_sql
+ #join_sql
+' order by [Subject]; ')
;
CREATE TABLE mytable
([ID] int, [Subject] varchar(7), [Users] varchar(5))
;
INSERT INTO mytable
([ID], [Subject], [Users])
VALUES
(1, 'Hi!', 'Anna'),
(2, 'Hi!', 'Peter'),
(3, 'Try', 'Jan'),
(4, 'Try', 'Peter'),
(5, 'Try', 'Jan'),
(6, 'Problem', 'Anna'),
(7, 'Problem', 'José'),
(8, 'Test', 'John'),
(9, 'Test', 'John'),
(10, 'Hi!', 'Anna'),
(11, 'Hi!', 'José'),
(12, 'Hi!', 'Anna'),
(13, 'Hi!', 'Joe')
;
select distinct subject,
(select users from (
select distinct users from mytable where subject=m.subject) a order by users offset 0 rows fetch next 1 row only) user1,
(select users from (
select distinct users from mytable where subject=m.subject) a order by users offset 1 rows fetch next 1 row only) user2,
(select users from (
select distinct users from mytable where subject=m.subject) a order by users offset 2 rows fetch next 1 row only) user3,
(select users from (
select distinct users from mytable where subject=m.subject) a order by users offset 3 rows fetch next 1 row only) user4
from mytable m
you can use below dynamic query to get the result-
create table test_Raw(ID int ,Subject varchar(100), Users varchar(100))
insert into test_Raw
values (1,' Hi!','Anna'),
(2,' Hi!','Peter'),
(3,'Try','Jan'),
(4,'Try','Peter'),
(5,'Try','Jan'),
(6,'Problem','Anna'),
(7,'Problem','José'),
(8,'Test','John'),
(9,'Test','John'),
(10,' Hi!','Anna'),
(11,' Hi!','José'),
(12,' Hi!','Anna'),
(13,' Hi!','Joe')
--select * from test_Raw
select dense_RANK() over( order by Subject) Ranking1, dense_RANK() over(partition by Subject order by users) Ranking2 , Subject , Users
into test
from test_Raw
group by Subject , Users
order by 3
declare #min int , #mx int , #Select nvarchar(max) , #from nvarchar(max) , #vmin varchar(3)
select #min= 1 , #mx = MAX(Ranking2) , #Select= 'select ' , #from = ' from test t1 ' , #vmin = '' from test
while (#min<=#mx)
begin
select #vmin = CAST(#min as varchar(3))
select #Select = #Select + CASE WHEN #min = 1 THEN 't1.Ranking1 as ID , t1.Subject , t1.Users AS User1 ' ELSE ',t' +#vmin+'.Users as User'+#vmin END
select #from = #from + CASE WHEN #min = 1 THEN '' ELSE ' left join test t'+#vmin + ' on t1.Ranking1 = t' + #vmin + '.Ranking1 and t1.Ranking2 + ' + cast (#min-1 as varchar(10)) + ' = t'+#vmin+'.Ranking2' END
set #min = #min + 1
end
select #Select = #Select + #from + ' where t1.Ranking2 = 1'
exec sp_executesql #Select

How to add a Column to stored procedure result?

I have the following sql procedure:
DECLARE #temp table
(
Column1 nvarchar(1000)
)
INSERT #temp (Column1)
SELECT fld_4
FROM MyTable
WHERE fld_1 = #param1 and
fld_2 = #param2 and
fld_3 = #param3
SELECT ROW_NUMBER() OVER(ORDER BY Column1 ASC) AS Number, Split.a.value('.', 'VARCHAR(100)') AS Result
FROM
(
SELECT Column1,
CAST ('<M>' + REPLACE(Column1, ';', '</M><M>') + '</M>' AS XML) AS Result
FROM #temp
) AS A CROSS APPLY Result.nodes ('/M') AS Split(a);
Structure of MyTable:
| fld_1 | fld_2 | fld_3 | fld_4 | ... | fld_9 | ...|
Where fld_4 contains something like this:
-9;-9;-1;-9;-9;-9;-9;-9;-1;-9;-9;-9;-9;-9;-9;-9;-9;-9;-1;-9;-9;-9;-9;-9;-9;-9;-9;-9;-1;-9;-1;-9;-9;-9;-1;-9;-9;-9;-9;-9;-9;-1;-1;-1;-1;-9;-1;-1;-9;-9;-9;-9;-1;-9;-1;-9;-9;-9;-1;-9;-1;-9;-1;-9;-9;-9;-9;-1;-9;-9;-1;-1;-9;-1;-1;0000;FFF8;-9;-9;-9;-1;-9;-1;-9;FFF6;-9;-1;-9;-1;-9;-1;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9;-9
My procedure returns a table with this structure:
| Number | Result |
| 1 | -9 |
| 2 | -9 |
| 3 | -1 |
| ... | ... |
Now, I want to achieve the following result:
| Number | Result | NewColumn |
| 1 | -9 | Value of fld_9 |
| 2 | -9 | Value of fld_9 |
| 3 | -1 | Value of fld_9 |
| ... | ... | Value of fld_9 |
Any suggestions?
You cannot call a Stored Procedure result directly..
However you can make view or or table-valued user-defined function then get results..
Other way insert Stored Procedure result on TempTable
INSERT INTO #tempTable EXEC MyStoredProcedure
look at this Quick Sample
Create PROCEDURE SampleStoreProc
AS
BEGIN
Select 'Burak', 1
END
GO
Create Table #TempTable
(
MyCol Varchar(50),
ReferanceCol int
)
Insert into #TempTable Exec SampleStoreProc
go
Create Table TestTable2
(
MyCol2 varchar(250),
RefCol int
);
go
Insert into TestTable2 values ('Yeni', 1);
Select a.MyCol, b.MyCol2 From #TempTable a
left join TestTable2 b on b.RefCol = a.ReferanceCol
If I understand what you are asking, you simply want another column included in your result set. Something like the following snippet should work. Keep your FROMclause, and add , MyTable to the end of it.
...
SELECT
ROW_NUMBER() OVER(ORDER BY Column1 ASC) AS Number
, Split.a.value('.', 'VARCHAR(100)') AS Result
, fld_9 AS NewColumn
FROM
...
, MyTable
WHERE
MyTable.fld_1 = #param1 AND
MyTable.fld_2 = #param2 AND
MyTable.fld_3 = #param3;

How to get detail table records as string in SQL Server

I have a table in database which contains hospital names as follow:
+------------+--------------+
| HospitalID | HospitalName |
+------------+--------------+
| 1 | Hosp1 |
| 2 | Hosp2 |
| 3 | Hosp3 |
| 4 | Hosp4 |
+------------+--------------+
Another table also exist which contains activity names as follows:
+------------+--------------+
| ActivityID | ActivityName |
+------------+--------------+
| 1 | Act1 |
| 2 | Act2 |
| 3 | Act3 |
| 4 | Act4 |
| 5 | Act5 |
+------------+--------------+
There's a N*M relation between these tables, i.e. each hospital can operate different activities. Therefore another table is required as follows:
+----+------------+------------+
| ID | HospitalID | ActivityID |
+----+------------+------------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 5 |
| 4 | 2 | 1 |
| 5 | 2 | 3 |
| 6 | 3 | 2 |
+----+------------+------------+
I want to write a select statement which selects hospital names and their related activities in a string field as follows:
+--------------+------------------+
| HospitalName | ActivityNames |
+--------------+------------------+
| Hosp1 | Act1, Act2, Act5 |
| Hosp2 | Act1, Act3 |
| Hosp3 | Act2 |
| Hosp4 | |
+--------------+------------------+
I have written the select statement using a function for ActivityNames field using a cursor but it is not optimized and the system performance decreases as the number of records increases.
Any solution or suggestion on how to solve this problem?
You can do this just with a select. No need of looping or Cursor for this. Looping will make performance degrade.
So the Schema will be
CREATE TABLE #HOSPITAL( HOSPITALID INT, HOSPITALNAME VARCHAR(20))
INSERT INTO #HOSPITAL
SELECT 1, 'HOSP1'
UNION ALL
SELECT 2 , 'HOSP2'
UNION ALL
SELECT 3 ,'HOSP3'
UNION ALL
SELECT 4 , 'HOSP4'
CREATE TABLE #ACTIVITY( ActivityID INT, ActivityName VARCHAR(50) )
INSERT INTO #ACTIVITY
SELECT 1, 'Act1'
UNION ALL
SELECT 2, 'Act2'
UNION ALL
SELECT 3, 'Act3'
UNION ALL
SELECT 4, 'Act4'
UNION ALL
SELECT 5, 'Act5'
CREATE TABLE #HOSPITAL_ACT_MAP(ID INT, HospitalID INT, ActivityID INT)
INSERT INTO #HOSPITAL_ACT_MAP
SELECT 1, 1, 1
UNION ALL
SELECT 2, 1, 2
UNION ALL
SELECT 3, 1, 5
UNION ALL
SELECT 4, 2, 1
UNION ALL
SELECT 5, 2, 3
UNION ALL
SELECT 6, 3, 2
And do Select like below with CTE
;WITH CTE AS (
SELECT DISTINCT H.HOSPITALNAME, A.ActivityName FROM #HOSPITAL_ACT_MAP HA
INNER JOIN #HOSPITAL H ON HA.HospitalID = H.HOSPITALID
INNER JOIN #ACTIVITY A ON HA.ActivityID = A.ActivityID
)
SELECT HOSPITALNAME
, (SELECT STUFF((SELECT ','+ActivityName FROM CTE C1
WHERE C1.HOSPITALNAME = C.HOSPITALNAME
FOR XML PATH('')),1,1,''))
FROM CTE C
GROUP BY HOSPITALNAME
Edit from Comments
If you can't use CTE and Stuff go for Method 2
DECLARE #TAB TABLE (HOSPITALNAME VARCHAR(20),ActivityName VARCHAR(20) )
INSERT INTO #TAB
SELECT DISTINCT H.HOSPITALNAME, A.ActivityName FROM #HOSPITAL_ACT_MAP HA
INNER JOIN #HOSPITAL H ON HA.HospitalID = H.HOSPITALID
INNER JOIN #ACTIVITY A ON HA.ActivityID = A.ActivityID
SELECT HOSPITALNAME, SUBSTRING(ACTIVITIES,1, LEN(ACTIVITIES)-1) FROM(
SELECT DISTINCT HOSPITALNAME,(SELECT ActivityName+',' FROM #TAB T1
WHERE T1.HOSPITALNAME = T.HOSPITALNAME
FOR XML PATH('') ) AS ACTIVITIES FROM #TAB T
)A
Note: For the performance purpose I have stored the Intermediate result on #TAB (Table variable). If you want you can directly Query it with Sub Query.
using STUFF function to achieve your result :
CREATE TABLE #Hospital(HospitalID INT,HospitalName VARCHAR(100))
CREATE TABLE #Activity(ActivityID INT,ActivityName VARCHAR(100))
CREATE TABLE #RelationShip(Id INT,HospId INT,ActId INT)
CREATE TABLE #ConCat(HospitalID INT ,HospName VARCHAR(100), ActName
VARCHAR(100),UpFlag TINYINT DEFAULT(0))
DECLARE #HospId INT = 0,#String VARCHAR(200) = ''
INSERT INTO #Hospital(HospitalID ,HospitalName )
SELECT 1,'Hosp1' UNION ALL
SELECT 2,'Hosp2' UNION ALL
SELECT 3,'Hosp3' UNION ALL
SELECT 4,'Hosp4'
INSERT INTO #Activity(ActivityID ,ActivityName )
SELECT 1,'Act1' UNION ALL
SELECT 2,'Act2' UNION ALL
SELECT 3,'Act3' UNION ALL
SELECT 4,'Act4' UNION ALL
SELECT 5,'Act5'
INSERT INTO #RelationShip(ID,HospId,ActId)
SELECT 1 , 1 , 1 UNION ALL
SELECT 2 , 1 , 2 UNION ALL
SELECT 3 , 1 , 5 UNION ALL
SELECT 4 , 2 , 1 UNION ALL
SELECT 5 , 2 , 3 UNION ALL
SELECT 6 , 3 , 2
SELECT HospitalName , STUFF( ( SELECT ',' + ActivityName FROM #Activity
JOIN #RelationShip ON ActId = ActivityID WHERE HospId = HospitalID FOR XML
PATH('') ),1,1,'')
FROM #Hospital
GROUP BY HospitalID,HospitalName
***FOR SQLServer2005 Use below code***
INSERT INTO #ConCat (HospitalID ,HospName)
SELECT DISTINCT HospitalID ,HospitalName
FROM #Hospital
WHILE EXISTS(SELECT 1 FROM #ConCat WHERE UpFlag = 0)
BEGIN
SELECT #HospId = HospitalID FROM #ConCat WHERE UpFlag = 0 ORDER BY
HospitalID
SET #String = ''
SELECT #String = ISNULL(#String,'') + CAST(A.ActivityName AS VARCHAR) +
',' FROM
(
SELECT ActivityName
FROM #RelationShip
JOIN #Activity ON ActId = ActivityID
WHERE HospId = #HospId
) A
UPDATE #ConCat SET UpFlag = 1,ActName = CASE WHEN #String = '' THEN
#String ELSE SUBSTRING(#String,0,LEN(#String) ) END WHERE HospitalID
= #HospId
END
SELECT * FROM #ConCat
You can use json to increase the performance of front end.
There is no particular solution if you are using open source databases.
Try to use IBM db2 or ORACLE database to ensure performance of your app.
then generate json data . You will find the improvement in speed

SQL SELECT: concatenated column with line breaks and heading per group

I have the following SQL result from a SELECT query:
ID | category| value | desc
1 | A | 10 | text1
2 | A | 11 | text11
3 | B | 20 | text20
4 | B | 21 | text21
5 | C | 30 | text30
This result is stored in a temporary table named #temptab. This temporary table is then used in another SELECT to build up a new colum via string concatenation (don't ask me about the detailed rationale behind this. This is code I took from a colleague). Via FOR XML PATH() the output of this column is a list of the results and is then used to send mails to customers.
The second SELECT looks as follows:
SELECT t1.column,
t2.column,
(SELECT t.category + ' | ' + t.value + ' | ' + t.desc + CHAR(9) + CHAR(13) + CHAR(10)
FROM #temptab t
WHERE t.ID = ttab.ID
FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)') AS colname
FROM table1 t1
...
INNER JOIN #temptab ttab on ttab.ID = someOtherTable.ID
...
Without wanting to go into too much detail, the column colname becomes populated with several entries (due to multiple matches) and hence, a longer string is stored in this column (CHAR(9) + CHAR(13) + CHAR(10) is essentially a line break). The result/content of colname looks like this (it is used to send mails to customers):
A | 10 | text1
A | 11 | text11
B | 20 | text20
B | 21 | text21
C | 30 | text30
Now I would like to know, if there is a way to more nicely format this output string. The best case would be to group the same categories together and add a heading and empty line between different categories:
*A*
A | 10 | text1
A | 11 | text11
*B*
B | 20 | text20
B | 21 | text21
*C*
C | 30 | text30
My question is: How do I have to modify the above query (especially the string-concatenation-part) to achieve above formatting? I was thinking about using a GROUP BY statement, but this obviously does not yield the desired result.
Edit: I use Microsoft SQL Server 2008 R2 (SP2) - 10.50.4270.0 (X64)
Declare #YourTable table (ID int,category varchar(50),value int, [desc] varchar(50))
Insert Into #YourTable values
(1,'A',10,'text1'),
(2,'A',11,'text11'),
(3,'B',20,'text20'),
(4,'B',21,'text21'),
(5,'C',30,'text30')
Declare #String varchar(max) = ''
Select #String = #String + Case when RowNr=1 Then Replicate(char(13)+char(10),2) +'*'+Category+'*' Else '' end
+ char(13)+char(10) + category + ' | ' + cast(value as varchar(25)) + ' | ' + [desc]
From (
Select *
,RowNr=Row_Number() over (Partition By Category Order By Value)
From #YourTable
) A Order By Category, Value
Select Substring(#String,5,Len(#String))
Returns
*A*
A | 10 | text1
A | 11 | text11
*B*
B | 20 | text20
B | 21 | text21
*C*
C | 30 | text30
This should return what you want
Declare #YourTable table (ID int,category varchar(50),value int, [desc] varchar(50))
Insert Into #YourTable values
(1,'A',10,'text1'),
(2,'A',11,'text11'),
(3,'B',20,'text20'),
(4,'B',21,'text21'),
(5,'C',30,'text30');
WITH Categories AS
(
SELECT category
,'**' + category + '**' AS CatCaption
,ROW_NUMBER() OVER(ORDER BY category) AS CatRank
FROM #YourTable
GROUP BY category
)
,Grouped AS
(
SELECT c.CatRank
,0 AS ValRank
,c.CatCaption AS category
,-1 AS ID
,'' AS Value
,'' AS [desc]
FROM Categories AS c
UNION ALL
SELECT c.CatRank
,ROW_NUMBER() OVER(PARTITION BY t.category ORDER BY t.Value)
,t.category
,t.ID
,CAST(t.value AS VARCHAR(100))
,t.[desc]
FROM #YourTable AS t
INNER JOIN Categories AS c ON t.category=c.category
)
SELECT category,Value,[desc]
FROM Grouped
ORDER BY CatRank,ValRank
The result
category Value desc
**A**
A 10 text1
A 11 text11
**B**
B 20 text20
B 21 text21
**C**
C 30 text30