How to use Coalesce for string concatenation in a subquery? - sql

I'm trying to string concatenate multiple row values from one table using "Coalesce", separated by comma and list it as a column in a subquery.
Something along the line of
Declare #assignTo nvarchar(4000)
Select
table1.columnA
table1.columnB
(
select #assignTo = Coalesce(#assignTo + ', ', '') + CAST(Name as nvarchar(250))
from
table2
where
...
)
from table1
where
.....
I keep getting "Incorrect syntax near '='."
If I just try to execute the subquery where the Coalesce function is called, its' fine. i.e
Declare #assignTo nvarchar(4000)
select #assignTo = Coalesce(#assignTo + ', ', '') + CAST(Name as nvarchar(250))
from
table2
where
...
Select #assignTo
That's fine. So my question is, how do I include it as a subquery?
Thanks a lot
ps: This is specific to SQL server 2000.

You can't include it as a subquery: you'll have to move it into a UDF.
In SQL Server 2005 you can with the XML PATH technique. But for SQL Server 2000 you have to have a separate scalar UDF with table access and the concatenation

As far as I know,
You can do like this if u prefer to do as SubQuery.
But the above solution is the most convenient one.
Declare #assignTo nvarchar(4000)
Select
table1.columnA
table1.columnB
tmp.[c]
from table1,
(
select #assignTo = Coalesce(#assignTo + ', ', '') + CAST(Name as nvarchar(250)) as [c]
from
table2
where
...
) as tmp
where
Hope it works!

Related

how to replace a comma with single quote comma in SQLIN clause

Hi all I have a an where clause like below
select * from table1
where colum1 IN (?parameter)
when I pass the values to the parameter they show up like below
('1,2,3') but to execute the query I need to change the values as ('1','2','3')
is there a way to replace the commas with single quotes comma in IN clause directly?
There is one hack to do what you want, using like:
select *
from table1
where ',' || column1 || ',' like '%,' || (?parameter) || ',%';
This functions, but it will not make use of an index on column1. You should think about other solutions, such as:
Parsing the string into a table variable.
Using in with a fixed number of parameters.
Storing the values in a table.
There may be other Oracle-specific solutions as well.
Use MS SQL, you can convert it into table value and using join for your condition, I am not familiar oracle but you can find same way to do it.
DECLARE #IDs varchar(max) ='1,2,3';
;WITH Cte AS
(
SELECT
CAST('<ID>' + REPLACE( #IDs, ',' , '</ID><ID>') + '</ID>' AS XML) AS IDs
)
SELECT '''' + Split.a.value('.', 'VARCHAR(100)') +'''' AS ID FROM Cte
CROSS APPLY Cte.IDs.nodes('/ID') Split(a)
You can achieve it using with clause. Logic here is to convert each comma separated value into different row.
with temp_tab as (
select replace(regexp_substr(parameter, '[^,]+',1, level),'''','') as str
from dual
connect by level<= length(regexp_replace(parameter, '[^,]+'))+1 )
select * from table1 where column1 in (select str from temp_tab);

SQL Server convert NULL to empty string in select *

I need to execute the following:
SELECT * FROM [MY_TVF](9186)
FOR XML AUTO, ELEMENTS
And replace all NULL values with an empty string '' to include them in the XML. I know I can spit out the elements with an xsi:nil="true" attribute by setting ELEMENTS XSINIL, but I don't want that.
I found this question: Convert NULL to Empty String SQL Server, where the answer says I can use ISNULL() around my query. I tried it like so:
ISNULL((SELECT * FROM [MY_TVF](9186)),'')
FOR XML AUTO,ELEMENTS
But I can't get it to work. I get the following error:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ','.
What can I do to simply replace all NULL values with an empty string so they are included in the XML?
Edit
There is no way to replace the * by column names. There is a reason we use a TVF, there are about 40 columns and they might change over time. My query is just to select everything and return it as XML.
I have deleted my previous answer and here is the latest one:
Declare #ColName as Varchar(max)
SEt #ColName=''
SELECT #ColName= COALESCE( #ColName + ' ISNULL(' +c.name + ','''') ','', '') +
c.name + ', '
FROM sysobjects o
JOIN syscolumns c ON o.id = c.id
WHERE o.xtype = 'U'
AND (o.name ='tbName')
SEt #ColName= ( 'Select ' + SUBSTRING(#ColName,0,LEN(#ColName)-1) + ' FROM tbName')
print #colname
EXEC(#ColName)
Get out of the habit of SELECT *
See if this works.
SELECT Col1,Col2,Col3,Col4,Col5
FROM
(
SELECT
ISNULL(Col1,'') Col1,
ISNULL(Col2,'') Col2,
ISNULL(Col3,'') Col3,
ISNULL(Col4,'') Col4,
ISNULL(Col5,'') Col5
FROM [MY_TVF](9186)
) T
FOR XML AUTO,ELEMENTS

SQL Query to List

I have a table variable in a stored procedure. What I want is to find all of the unique values in one column and join them in a comma-separated list. I am already in a stored procedure, so I can do it some way that way; however, I am curious if I can do this with a query. I am on SQL Server 2008. This query gets me the values I want:
SELECT DISTINCT faultType FROM #simFaults;
Is there a way (using CONCAT or something like that) where I can get the list as a single comma-separated value?
This worked for me on a test dataset.
DECLARE #MyCSV Varchar(200) = ''
SELECT #MyCSV = #MyCSV +
CAST(faulttype AS Varchar) + ','
FROM #Simfaults
GROUP BY faultType
SET #MyCSV = LEFT(#MyCSV, LEN(#MyCSV) - 1)
SELECT #MyCSV
The last part is needed to trim the trailing comma.
+1 to JNK - the other common way you will see, which doesn't require a variable is:
SELECT DISTINCT faulttype + ','
FROM #simfaults
FOR XML PATH ('')
Note that if faulttype contains characters like "<" for example, those will be xml encoded. But for simple values this will be OK.
this is how we do this
create table #test (item int)
insert into #test
values(1),(2),(3)
select STUFF((SELECT ', ' + cast(Item as nvarchar)
FROM #test
FOR XML PATH('')), 1, 2, '')
Without the space after the comma it would be;
select STUFF((SELECT ',' + cast(Item as nvarchar)
FROM #test
FOR XML PATH('')), 1,1, '')

What is the best way to collapse the rows of a SELECT into a string?

In a SQL statement ( or procedure ) I want to collapse the rows of this table into a single comma delimited string.
simpleTable
id value
-- -----
1 "a"
2 "b"
3 "c"
Collapse to:
"a, b, c"
You can concatenate using an embedded 'set' statement in a query:
declare #combined varchar(2000)
select #combined = isnull(#combined + ', ','') + isnull(value,'')
from simpleTable
print #combined
(Note that the first isnull() initialises the string, and the second isnull() is especially important if there's any chance of nulls in the 'value' column, because otherwise a single null could wipe out the whole concatenation)
(edited code and explanation after comments)
Edit (ten years later):
SQL Server 2017 introduced the STRING_AGG() function which provides an official way of concatenating strings from different rows. Like other aggregation functions such as COUNT(), it can be used with GROUP BY.
So for the example above you could do:
select string_agg(value, ', ')
from simpleTable
If you had some other column and you wanted to concatenate for values of that column, you would add a 'group by' clause, e.g:
select someCategory, string_agg(value, ', ') as concatValues
from simpleTable
group by someCategory
Note string_agg will only work with SQL 2017 and above.
This will only work in MSSQL 2005+
select value + ',' from simpletable for xml path ('')
..one way to prevent the extra comma:
select case(row_number() over (order by id))
when 1 then value else ',' + value end
from simpletable
for xml path ('')
DECLARE #EmployeeList varchar(100)
SELECT #EmployeeList = COALESCE(#EmployeeList + ', ', '') +
CAST(Emp_UniqueID AS varchar(5))
FROM SalesCallsEmployees
WHERE SalCal_UniqueID = 1
SELECT #EmployeeList
Results:
1, 2, 4
This is based on #codeulike answer, but will prevent losing the portion of the string that gets concatenated before a null "value" is concatenated on.
declare #combined varchar(2000)
select #combined = isnull(#combined + ', ','') + ISNULL(value,'')
from simpleTable
print #combined

How to return multiple values in one column (T-SQL)?

I have a table UserAliases (UserId, Alias) with multiple aliases per user. I need to query it and return all aliases for a given user, the trick is to return them all in one column.
Example:
UserId/Alias
1/MrX
1/MrY
1/MrA
2/Abc
2/Xyz
I want the query result in the following format:
UserId/Alias
1/ MrX, MrY, MrA
2/ Abc, Xyz
Thank you.
I'm using SQL Server 2005.
p.s. actual T-SQL query would be appreciated :)
You can use a function with COALESCE.
CREATE FUNCTION [dbo].[GetAliasesById]
(
#userID int
)
RETURNS varchar(max)
AS
BEGIN
declare #output varchar(max)
select #output = COALESCE(#output + ', ', '') + alias
from UserAliases
where userid = #userID
return #output
END
GO
SELECT UserID, dbo.GetAliasesByID(UserID)
FROM UserAliases
GROUP BY UserID
GO
Well... I see that an answer was already accepted... but I think you should see another solutions anyway:
/* EXAMPLE */
DECLARE #UserAliases TABLE(UserId INT , Alias VARCHAR(10))
INSERT INTO #UserAliases (UserId,Alias) SELECT 1,'MrX'
UNION ALL SELECT 1,'MrY' UNION ALL SELECT 1,'MrA'
UNION ALL SELECT 2,'Abc' UNION ALL SELECT 2,'Xyz'
/* QUERY */
;WITH tmp AS ( SELECT DISTINCT UserId FROM #UserAliases )
SELECT
LEFT(tmp.UserId, 10) +
'/ ' +
STUFF(
( SELECT ', '+Alias
FROM #UserAliases
WHERE UserId = tmp.UserId
FOR XML PATH('')
)
, 1, 2, ''
) AS [UserId/Alias]
FROM tmp
/* -- OUTPUT
UserId/Alias
1/ MrX, MrY, MrA
2/ Abc, Xyz
*/
DECLARE #Str varchar(500)
SELECT #Str=COALESCE(#Str,'') + CAST(ID as varchar(10)) + ','
FROM dbo.fcUser
SELECT #Str
group_concat() sounds like what you're looking for.
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
since you're on mssql, i just googled "group_concat mssql" and found a bunch of hits to recreate group_concat functionality. here's one of the hits i found:
http://www.stevenmapes.com/index.php?/archives/23-Recreating-MySQL-GROUP_CONCAT-In-MSSQL-Cross-Tab-Query.html
You can either loop through the rows with a cursor and append to a field in a temp table, or you could use the COALESCE function to concatenate the fields.
Sorry, read the question wrong the first time. You can do something like this:
declare #result varchar(max)
--must "initialize" result for this to work
select #result = ''
select #result = #result + alias
FROM aliases
WHERE username='Bob'