get all row values in single record - sql

i have a table in which i want to get column values into single record separated by comma

using the stuff() with select ... for xml path ('') method of string concatenation.
select col1, col2, col3 = stuff(
(
select ','+i.col3
from t as i
where i.col1 = t.col1
for xml path (''), type).value('.','nvarchar(max)')
,1,1,'')
from t
group by col1, col2
rextester demo: http://rextester.com/QXH88855
returns:
+------+------+-------------+
| col1 | col2 | col3 |
+------+------+-------------+
| 1 | roy | a,f,g,h |
| 2 | sam | h,k,l |
| 3 | joe | q,w,e,r,t,y |
+------+------+-------------+

If SQL Server 2017 or Vnext or SQL Azure you can use string_agg
SELECT col1, col2, STRING_AGG(col3, ',') from yourtable
GROUP BY col1, col2

Formatting the output really should be done in the program that receives the data. You can export from SQL Server Management studio to csv by selecting "output to file" on the toolbar and configuring comma delimited output.
If you really need to combine the columns into a comma separated single value:
SELECT CAST(col1 AS NVARCHAR(100)) + N',' + CAST(col2 AS NVARCHAR(100)) + N',' + CAST(col3 AS NVARCHAR(100))
FROM table

Related

How to select only a few columns of a table

I have a Table which contain around 1000 columns. When I use
Select *
from Table
Its Return entire record of the table. But I just want only limited column of the record.
col1 | col2 | col3 | col4 | col 5 | ......................... | col1000 |
| | | | | ------------------------- | |
| | | | | ------------------------- | |
| | | | | ------------------------- | |
| | | | | ------------------------- | |
------------------------------------------------------------------------------------------------------
I just need col5 to col1000 record data only.
you have to write all the columns that you need in select
select col5, col6, ......... ,col1000 from table
there is no shot-cut way with out it and select * means all the columns of your table
If you really want to do without typing each column name, one way is using dynamic query.
For example in SQL Server you can write the dynamic query like following.
DECLARE #selstmt AS NVARCHAR(max);
SET #selstmt = 'select ' + Stuff((SELECT ', ' + Quotename(NAME) FROM
( SELECT c.NAME FROM
sys.columns c JOIN sys.tables t ON c.object_id = t.object_id
WHERE t.NAME = 'yourtablename'
AND c.NAME NOT IN('col1', 'col2', 'col3', 'col4')
)t FOR
xml path(''), type).value('.',
'NVARCHAR(MAX)'), 1, 1, '');
SET #selstmt = #selstmt + ' from yourtable'
EXEC sp_executesql #selstmt
Specify column names that you want to select instead of using * operator.
SELECT * will return all columns for table
SELECT col5, col6, col7,...., col1000 (col5 upto col1000) will return only specified columns of the table
There actually is one easy way in SSMS.
SELECT * FROM TableA
Select this text, press CNTRL SHIFT Q
Then you have all the columns and can easily remove a few.
You have to write all columns.
SELECT col1, col2, col3 from table;
But...
Tested on MySQL
Since you have too many columns, you can run a query to select the desired columns from the table:
SELECT GROUP_CONCAT(COLUMN_NAME SEPARATOR ', ')
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'schemaName' AND TABLE_NAME = 'table'
AND COLUMN_NAME IN ('col1', 'col2', 'col3');
# or to filter the columns
# AND COLUMN_NAME NOT IN ('col1', 'col2', 'col3');
And build the query with the resultant columns.
GROUP_CONCAT outputs the values in a single row separated with a ,, so you can use them to query the table directly
SELECT
col1,col2,col3
FROM
table_name

SQL Query - Row to columns not really a pivot

I'm trying to move certain fields of an ID into columns, but it doesn't appear to match all the pivot examples I am finding. All the examples I can find use some form of a grouping on a field value. I want to use more of a placement regardless of the value in the field. I want to do this in a query without looping via code. Data source example (sorry couldn't figure out how to format a table on the post so I used a code snippet):
+----+--------+--------+
| ID | Field1 | Field2 |
+----+--------+--------+
| 1 | NULL | NULL |
| 2 | Jim | 321 |
| 2 | Jack | 54 |
| 2 | Sue | 985 |
| 2 | Gary | 654 |
| 3 | Herb | 332 |
| 3 | Chevy | 10 |
+----+--------+--------+
Result set I'm trying to generate:
+----+------+------+-------+------+------+------+
| ID | Col1 | Col2 | Col3 | Col4 | Col5 | Col6 |
+----+------+------+-------+------+------+------+
| 1 | NULL | NULL | | | | |
| 2 | Jim | 321 | Jack | 54 | Sue | 985 |
| 3 | Herb | 332 | Chevy | 10 | | |
+----+------+------+-------+------+------+------+
SQL Fiddle: http://sqlfiddle.com/#!3/a225a/1
;with cte as (
select id
, field1
, field2
, ROW_NUMBER() over (partition by id order by field1, field2) r
from #t
)
select c1.id
, c1.field1 col1
, c1.field2 col2
, c2.field1 col3
, c2.field2 col4
, c3.field1 col5
, c3.field2 col6
from cte c1
left outer join cte c2 on c2.id = c1.id and c2.r = c1.r + 1
left outer join cte c3 on c3.id = c1.id and c3.r = c1.r + 2
where (c1.r % 3) = 1
Explanation
ROW_NUMBER() over (partition by id order by field1, field2) r. This line ensures that we have a column counting up from 1 for each id. This allows us to distinguish between the multiple rows.
The CTE is used to save typing the same statement for c1, c2 and c3.
The joins ensure that all items in a row have the same id, and that data for col1, col3 and col5 (likewise for col2, col4 and col6) is taken from consecutive rows. We're using left outer joins because there may not rows in the source table for these columns.
The where statement says to take the first row of each set of 3 for the data in c1 (with c2 and c3 thus being the second and third of each set, thanks to the earlier join).
Here's a solution using dynamic sql that works though I'm sure there's a better way to do it. Caution, it's a bit painful. First it builds the list of columns to pivot and select, builds the dynamic sql and runs it.
DECLARE #PivotColumns as varchar(max), #SelectColumns as varchar(max), #sql as varchar(max)
SELECT #PivotColumns = ISNULL(#PivotColumns + ',', '') + ColNum,
#SelectColumns = ISNULL(#SelectColumns + ',', '') + 'NULLIF(' + ColNum + ', ''NULL'') as ' + ColNum
from (select distinct 'Col' + cast(ROW_NUMBER() OVER (partition by id order by id) as varchar) as ColNum
from (select id,
isnull(field1,'NULL') as field1,
isnull(field2,'NULL') as field2
from weirdpivot) cols
unpivot
(
value
for col in (field1, field2)
) unpivoted) DistinctColumns
set #sql = '
select id, + ' + #SelectColumns + '
from (select
''Col'' + cast(ROW_NUMBER() OVER (partition by id order by id) as varchar) as colnum
,id
,value
from (select id,
isnull(field1,''NULL'') as field1,
isnull(field2,''NULL'') as field2
from weirdpivot) cols
unpivot
(
value
for col in (field1, field2)
) u) unpivoted
pivot
(
max(value)
for colnum in (' + #PivotColumns + ')
) p'
exec (#sql)

Group Concat in Redshift

I have a table like this:
| Col1 | Col2 |
|:-----------|------------:|
| 1 | a;b; |
| 1 | b;c; |
| 2 | c;d; |
| 2 | d;e; |
I want the result to be some thing like this.
| Col1 | Col2 |
|:-----------|------------:|
| 1 | a;b;c;|
| 2 | c;d;e;|
Is there some way to write a set function which adds unique values in a column into an array and then displays them. I am using the Redshift Database which mostly uses postgresql with the following difference:
Unsupported PostgreSQL Functions
Have a look at Redshift's listagg() function which is similar to MySQL's group_concat. You would need to split the items first and then use listagg() to give you a list of values. Do take note, though, that, as the documentation states:
LISTAGG does not support DISTINCT expressions
(Edit: As of 11th October 2018, DISTINCT is now supported. See the docs.)
So will have to take care of that yourself. Assuming you have the following table set up:
create table _test (col1 int, col2 varchar(10));
insert into _test values (1, 'a;b;'), (1, 'b;c;'), (2, 'c;d;'), (2, 'd;e;');
Fixed number of items in Col2
Perform as many split_part() operations as there are items in Col2:
select
col1
, listagg(col2, ';') within group (order by col2)
from (
select col1, split_part(col2, ';', 1) as col2 from _test
union select col1, split_part(col2, ';', 2) as col2 from _test
)
group by col1
;
Varying number of items in Col2
You would need a helper here. If there are more rows in the table than items in Col2, a workaround with row_number() could work (but is expensive for large tables):
with _helper as (
select
(row_number() over())::int as part_number
from
_test
),
_values as (
select distinct
col1
, split_part(col2, ';', part_number) as col2
from
_test, _helper
where
length(split_part(col2, ';', part_number)) > 0
)
select
col1
, listagg(col2, ';') within group (order by col2) as col2
from
_values
group by
col1
;

Pivot and merge columns in a SQL Server stored procedure

I have a table with the following columns
Col1(bigint) | Col2(datetime)| Col3(nvarchar(100))| Col4(xml)
The 4th column is a xml which looks like following, it may contain any number of fields
<Fields>
<Field1>10</Field1>
<Field2>11</Field2>
<Field3>10</Field3>
<Field4>11</Field4>
</Fields>
I need to query multiple rows from the table. I am creating a stored procedure which gets 2 parameters
Parameter1: #query (type of xml)
<Rowset>
<Row>
<Col1>20140510123205321</Col1>
<Col2>2014-05-14T13:01:03.1426856+05:30</Col2>
<Col3>Source1</Col3>
</Row>
<Row>
<Col1>20140510123205322</Col1>
<Col2>2014-05-14T13:01:03.1426856+05:30</Col2>
<Col3>Source2</Col3>
</Row>
</Rowset>
Parameter2: #Fields (type of string comma separated)
Field1,Field2,Field3,Field4
I am expecting a output in the following format
Col1 | Col2 | Col3 | Field1 | Field2 | Field3 | Field4
-----------------------------------------------------------------
2014051092|2014-05-14|Source1| 10 | 21 | 12 | 43
2014051093|2014-05-14|Source1| 11 | 22 | 23 | 53
I have created a table from the first parameter in the stored procedure.
INSERT INTO #TempPricing
(
Col1,
Col2,
Col3
)
SELECT
Col1,
Col2,
Col3
FROM OPENXML(#handle, '/Rowset/Row', 2)
WITH
(
Col1 bigint,
Col2 datetime,
Col3 varchar(50)
)
How can I pivot the second parameter after splitting, merge it with the table above and fetch the data?
EDIT
The output can also be the following format
Col1 | Col2 | Col3 | Fields
--------------------------------------
2014051092|2014-05-14|Source1|<Fields><Field1>10</Field1><Field1>11</Field1></Fields>
2014051093|2014-05-14|Source1|<Fields><Field1>20</Field1><Field1>21</Field1></Fields>
so any of the above formats will work
Lets try the below script it may help you.
declare #String varchar(max), #Result varchar(max)
select #String= COALESCE(#String+',', '')+ QUOTENAME(Col1)
FROM (
select distinct Col1 from TableA A Inner Join dbo.Tab C VS on A.AttributeID =VS.AttributeId)AS B
set #Result ='
with pivotData AS
(
select distinct P.Col1, PA.col1,A.Col1,PA.col2 from Tab3 PA join Attribute A
on A.AttributeID=PA.AttributeID join Product P on P.ProductId=PA.ProductId
)
select Col1, Col2,
'+#String+' from pivotData
pivot(
Max(col2) for
Col1in('+#String+')
)as PR order by col3 desc'
exec (#Result)

Rotate one column and Select it comma seperated [duplicate]

This question already has answers here:
Inner Join Two Table, aggregating varchar fields
(2 answers)
Closed 8 years ago.
I have a table like this:
PK | COL1 | COL2
----------------
1 | A | a
2 | B | b
3 | C | c
4 | A | d
5 | A | e
6 | B | f
7 | C | g
8 | C | h
and I want to do an Select that I get the following result
COL1 | COL2
---------------
A | a,d,e
B | b,f
C | c,g,h
As I understand SQL at the moment I don't know how to do this without "programing" something extra e.q. with PL/SQL
But i search for an DBMS independent solution as good as it can be DBMS independent.
This is an Oracle (11.2) solution:
select col1,
listagg(col2, ',') within group (order by col1) as col2
from the_table
group by col1;
As you need this for other DBMS as well, this would be the Postgres solution:
select col1,
string_agg(col2, ',' order by col1) as col2
from the_table
group by col1;
For MySQL this would be:
select col1,
group_concat(col2 ORDER BY col1 SEPARATOR ',') as col2
from the_table
group by col1;
For a SQL Server solution, see Vijaykumar's answer.
try this !!
SELECT [col1],
SUBSTRING(d.col2,1, LEN(d.col2) - 1) col2
FROM
(
SELECT DISTINCT [col1]
FROM table1
) a
CROSS APPLY
(
SELECT [col2] + ', '
FROM table1 AS b
WHERE a.[col1] = b.[col1]
FOR XML PATH('')
) d (col2)