Return two rows as a single row - sql

Please see the SQL DDL below:
create table dbo.Test(id int, name varchar(30))
INSERT INTO Test values (1, 'Mark')
INSERT INTO Test values (2,'Williams')
I am trying to return: 'Mark Williams' using an SQL SELECT. I have tried using an SQL Pivot, but it has not worked.

Possibly more flexible than COALESCE would be to use the STUFF and FOR XML pattern:
SELECT TOP 1
STUFF((SELECT ' ' + Name AS [text()]
FROM dbo.Test
ORDER BY id
FOR XML PATH('')), 1, 1, '' ) Concatenated
FROM TEST

Try this:
DECLARE #Return VARCHAR(MAX)
SELECT #Return = COALESCE(#Return+' ','') + name
FROM dbo.TEST
SELECT #Return

DECLARE #NameList VARCHAR(8000)
SELECT #NameList = COALESCE(#NameList + ' ', '') + Name
FROM Test
SELECT #NameList
Read more COALESCE

Related

I want to transform multiple rows into a single row, single column and append comma (,) between the values with one Select Query

I want to convert multiple rows into a [single row, single column] and append comma (,) in between the values. I want to use one Select query with no declare statement and no Utility.
We can have any number of rows
Table:
ID
1
2
3
4
5
My desired Output: 1, 2, 3, 4, 5
If you don't want to use DECLARE, you can use STUFF i FOR XML PATH(''). For example:
DECLARE #tab TABLE (Id varchar(10))
INSERT INTO #tab VALUES ('1'),('2'),('3'),('4')
SELECT STUFF((SELECT ', ' + Id FROM #tab FOR XML PATH('')),1,2,'')
I assume, your Id column is type of int or bigint so you will have to cast it to char or varchar.
In SQL Server 2017 you can use STRING_AGG.
DECLARE #tab TABLE (Id varchar(10))
INSERT INTO #tab VALUES ('1'),('2'),('3'),('4')
SELECT STRING_AGG (Id, ', ')
FROM #tab;
DECLARE #Output VARCHAR(MAX)
SELECT #Output = ISNULL(<value> + ',',<value>) FROM <table>
SELECT #Output
In SQL Server you can use COALESCE
DECLARE #number VARCHAR(MAX);
SET #number = NULL;
SELECT
#number = COALESCE(#number+',', '')+ID
FROM Table
Select #Number
On Microsoft SQL Server:
DECLARE #CSVList VARCHAR(MAX)
SELECT #CSVList = COALESCE(#CSVList + ', ', '') + CAST(ID AS NVARCHAR(100))
FROM YourTable
SELECT #CSVList

Select non-empty columns using SQL Server

I am using SQL Server 2012. i have a table with 90 columns. I am trying to select only columns that contains data. After searching i used the following procedure:
1- Getting all columns count using one select query
2- Pivoting Result Table into a Temp table
3- Creating Select query
4- Executing this query
Here is the query i used:
DECLARE #strTablename varchar(100) = 'dbo.MyTable'
DECLARE #strQuery varchar(max) = ''
DECLARE #strSecondQuery varchar(max) = 'SELECT '
DECLARE #strUnPivot as varchar(max) = ' UNPIVOT ([Count] for [Column] IN ('
CREATE TABLE ##tblTemp([Column] varchar(50), [Count] Int)
SELECT #strQuery = ISNULL(#strQuery,'') + 'Count([' + name + ']) as [' + name + '] ,' from sys.columns where object_id = object_id(#strTablename) and is_nullable = 1
SELECT #strUnPivot = ISNULL(#strUnPivot,'') + '[' + name + '] ,' from sys.columns where object_id = object_id(#strTablename) and is_nullable = 1
SET #strQuery = 'SELECT [Column],[Count] FROM ( SELECT ' + SUBSTRING(#strQuery,1,LEN(#strQuery) - 1) + ' FROM ' + #strTablename + ') AS p ' + SUBSTRING(#strUnPivot,1,LEN(#strUnPivot) - 1) + ')) AS unpvt '
INSERT INTO ##tblTemp EXEC (#strQuery)
SELECT #strSecondQuery = #strSecondQuery + '[' + [Column] + '],' from ##tblTemp WHERE [Count] > 0
DROP TABLE ##tblTemp
SET #strSecondQuery = SUBSTRING(#strSecondQuery,1,LEN(#strSecondQuery) - 1) + ' FROM ' + #strTablename
EXEC (#strSecondQuery)
The problem is that this query is TOO SLOW. Is there a best way to achieve this?
Notes:
Table have only one clustered index on primary key Column ID and does not contains any other indexes.
Table is not editable.
Table contains very large data.
Query is taking about 1 minute to be executed
Thanks in advance.
I do not know if this is faster, but you might use one trick: FOR XML AUTO will ommit columns without content:
DECLARE #tbl TABLE(col1 INT,col2 INT,col3 INT);
INSERT INTO #tbl VALUES (1,2,NULL),(1,NULL,NULL),(NULL,NULL,NULL);
SELECT *
FROM #tbl AS tbl
FOR XML AUTO
This is the result: col3 is missing...
<tbl col1="1" col2="2" />
<tbl col1="1" />
<tbl />
Knowing this, you could find the list of columns, which are not NULL in all rows, like this:
DECLARE #ColList VARCHAR(MAX)=
STUFF
(
(
SELECT DISTINCT ',' + Attr.value('local-name(.)','nvarchar(max)')
FROM
(
SELECT
(
SELECT *
FROM #tbl AS tbl
FOR XML AUTO,TYPE
) AS TheXML
) AS t
CROSS APPLY t.TheXML.nodes('/tbl/#*') AS A(Attr)
FOR XML PATH('')
),1,1,''
);
SELECT #ColList
The content of #ColList is now col1,col2. This string you can place in a dynamically created SELECT.
UPDATE: Hints
It would be very clever, to replace the SELECT * with a column list created from INFORMATION_SCHEMA.COLUMNS excluding all not-nullable. And - if needed and possible - types, wich contain very large data (BLOBs).
UPDATE2: Performance
Don't know what your very large data means actually... Just tried this on a table with about 500.000 rows (with SELECT *) and it returned correctly after less than one minute. Hope, this is fast enough...
Try using this condition:
where #columnname IS NOT NULL AND #columnname <> ' '

Return SELECT query result as a CSV string

I have the following Sql Server 2016 SELECT statement that returns only 1 row:
SELECT TOP 1 * FROM tempdb.dbo.IMTD
How can I concatenate the values as a comma delimited string? NOTE: the column names of this temporary table are unknown as they can variate.
Thank you.
Something like this perhaps:
-- Sample data
DECLARE #someTable TABLE (SomeID int identity, SomeTxt varchar(100));
INSERT #someTable VALUES ('row1'),('row2'),('row3');
-- Solution
SELECT ConcatinatedString =
STUFF
((
SELECT ','+SomeTxt
FROM #someTable
FOR XML PATH(''), TYPE
).value('.','varchar(100)'),1,1,'');
You can use Dynamic query as below:
DECLARE #COLS VARCHAR(MAX) = ''
SELECT #COLS = #COLS + ',' + COLUMN_NAME
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE '#table[_]%' -- Dynamic Table (here, Temporary table)
DECLARE #COLNAMES VARCHAR(MAX) = REPLACE(STUFF(#COLS, 1, 1, ''), ',', '+ '','' +')
Declare #cmd varchar(max) = 'Select ' + #COLNAMES + ' as CSVCol from #table'
-- will generate
-- Select Column1+ ',' +Column2+ ',' +Column3 as CSVCol from #table
EXEC (#cmd)
Another solution you can try is this.
SELECT LTRIM(RTRIM(<ColumnName1>)) + ',',
LTRIM(RTRIM(<ColumnName2>)) + ',',
...
LTRIM(RTRIM(<ColumnNamen>)) + ','
FROM tempdb.dbo.IMTD
If you only want one row keep that top 1 In there like
SELECT TOP 1
LTRIM(RTRIM(<ColumnName1>)) + ',',
LTRIM(RTRIM(<ColumnName2>)) + ',',
...
LTRIM(RTRIM(<ColumnNamen>)) + ','
FROM tempdb.dbo.IMTD
The LTRIM and RTRIM will remove any white space and this should allow you to copy and paste the result set anywhere you may need it. You will need to do this for each columnname.
You can use the query below to get the column names from your temp table.
DECLARE #ColumnNames NVARCHAR(MAX)
SELECT
#ColumnNames= COALESCE(#ColumnNames +',','')+COLUMN_NAME
FROM
TempDB.INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = '#TempTableName'

Comma separated column value from Temporary Table

I am inserting select statement result to Temporary table. I want its one column value comma separated, so I tried following but it is not working.
SELECT #IdList = COALESCE(#IdList+',' ,'') + s.Id
FROM (SELECT Id FROM #_TempStudentTable) as s
I have checked data in #_TempStudentTable, it is having data. But when i try to display IdList, it returns NULL.
Help me. I don't know what's the problem.
Try this :
DECLARE #IdList VARCHAR(MAX)
SELECT #IdList = COALESCE(#IdList + ',','') + CAST(Id AS VARCHAR(100))
FROM #_TempStudentTable
SELECT #IdList
You can get it without variable also using XML like below
SELECT STUFF(( SELECT ',' + CAST(Id AS VARCHAR(10))
FROM #_TempStudentTable
FOR XML PATH (''))
, 1, 1, '')
In SQL Server, you may use the below query to get a list of comma separated column names/headers:
SELECT STUFF((
SELECT ',' + CAST(name AS VARCHAR(50))
FROM (
SELECT name
FROM tempdb.sys.columns
WHERE [object_id] = OBJECT_ID(N'tempdb..#temptablename')
) k
FOR XML PATH('')
), 1, 1, '')

How to write sql to convert one string from mutiple rows?

Supose I have a table with following kind of data:
Tab(id, myString)
1 A
2 B
3 C
...
I want to a SQL can return all one string for all values in Column myString. So the result I want looks like: "A, B, C"
If I don't want to use cursor and stored procedure, is it possible sql to get such kind of result?
Use T-SQL row concatenation:
declare #s varchar(max)
set #s = ''
select #s = #s +
case when #s = '' then '' else ', ' end + Letter
from MyTable
select #s
edited removed trailing ", "
A combination of using FOR XML PATH (providing an empty element name) and STUFF is a common SQL Server (2005+) technique. It doesn't require declaration of any local variables and can therefore be run outside of batch or procedure.
SELECT STUFF(
(SELECT ',' + t.myString
FROM TAB t
ORDER BY t.Id
FOR XML PATH('')),1,1,'') AS CSV
Declare #tbl table(ID nvarchar(1),[myString] nvarchar(100))
Insert into #tbl values(1,'A');
Insert into #tbl values(2,'B');
Insert into #tbl values(3,'C');
DECLARE #CSVList varchar(100)
SELECT #CSVList = COALESCE(#CSVList + ' , ', '') +
[myString]
FROM #tbl
SELECT #CSVList