Sql Query to display output horizontally - sql

I need to display a query output in a horizontal manner. I have some example data
create table TestTable (id number, name varchar2(10))
insert into TestTable values (1, 'John')
insert into TestTable values (2, 'Mckensy')
insert into TestTable values (3, 'Valneech')
insert into TestTable values (4, 'Zeebra')
select * from TestTable
This gets the output in a vertical view.
ID Name
==========
1 John
2 Mckensy
3 Valneech
4 Zeebra
However, I need to display it horizontally.
ID 1 2 3 4
Name John Mckensy Valneech Zeebra

create table #TestTable (id int, name varchar(10))
insert into #TestTable values (1, 'John')
insert into #TestTable values (2, 'Mckensy')
insert into #TestTable values (3, 'Valneech')
insert into #TestTable values (4, 'Zeebra')
select *
from
(
select *
from #TestTable
) src
pivot
(
max(name)
for id in ([1], [2], [3],[4])
) piv;
output
1 2 3 4
John Mckensy Valneech Zeebra

You can also use dynamic sql query something like below.
Query
declare #sql as varchar(max);
select #sql = 'select ' + char(39) + 'Name' + char(39) + ' Id,' + stuff((
select
',max(case [Id] when ' + cast(id as varchar(10)) + ' then name end) ['
+ cast([Id] as varchar(10)) + ']'
from TestTable
for xml path('')
), 1, 1, '');
select #sql += 'from TestTable;';
exec(#sql);

Related

Dynamic values in where clause

I am trying to read rows one by one from a table and pass values to the query condition. I am unable to proceed further. do I have to use counter /iteration or is there any options. Any help is much appreciated
I want to pass values into the value like condition
create table #temp
(
userid int,
typeid int
)
insert into #temp values (1, 101)
insert into #temp values (1, 221)
insert into #temp values (3, 401)
insert into #temp values (4, 501)
create table #target
(
userid int,
roleid int,
value varchar(max)
)
insert into #target values (1, 000, 'something here userid:1 typeid:101 something here')
insert into #target values (1, 001, 'something here userid:1 typeid:221 something here')
insert into #target values (1, 001, 'something here userid:1 typeid:331 something here')
insert into #target values (3, 002, 'something here userid:3 typeid:401 something here')
select t.userid, d.roleid, t.typeid
from #target d
inner join #temp t on t.userid = d.userid
and value like '%userid:'t.userid' typeid:'t.typeid'%'
This is the result I get:
userid
roleid
typeid
1
000
101
1
001
221
3
002
401
Seems you just need to familiarise yourself with the string concatenation operator:
select t.userid, roleid, typeid
-- How to debug such a query
--, [value]
--,'%userid:' + convert(varchar(32),t.userid) + ' typeid:' + convert(varchar(32),t.typeid) + '%'
--, case when d.[value] like '%userid:' + convert(varchar(32),t.userid) + ' typeid:' + convert(varchar(32),t.typeid) + '%' then 1 else 0 end
from #target d
inner join #temp t on t.userid = d.userid
and d.[value] like '%userid:' + convert(varchar(32),t.userid) + ' typeid:' + convert(varchar(32),t.typeid) + '%'
Returns
userid
roleid
typeid
1
0
101
1
1
221
3
2
401

I have a mobile column having data in the format 91-98-91254*** I want to display the data in 3 separate columns separeted by " - "

The query removes the " - " but then after that i want to display each set in 3 different columns`enter code here
SELECT SUBSTRING(RIGHT(REPLACE(mobile,'-',''),10),1,3) + ' ' +
SUBSTRING(RIGHT(REPLACE(mobile,'-',''),10),4,3) + ' ' +
SUBSTRING(RIGHT(REPLACE(mobile,'-',''),10),7,4)
FROM candidate_jitendra
Just list each number term as a separate column in your SELECT list:
SELECT SUBSTRING(RIGHT(REPLACE(mobile,'-',''),10),1,3) AS first,
SUBSTRING(RIGHT(REPLACE(mobile,'-',''),10),4,3) AS second,
SUBSTRING(RIGHT(REPLACE(mobile,'-',''),10),7,4) AS third
FROM candidate_jitendra
This is dynamically access the string and also not any hardcore position.
Declare #t table (id int, name varchar(50))
insert into #t (id,name) values( 1 ,'99-98-91254')
insert into #t (id,name) values( 2 ,'99-89-8681')
insert into #t (id,name) values( 3 ,'87')
insert into #t (id,name) values( 4 ,'786-32')
insert into #t (id,name) values( 5 ,'79-45-4')
;WITH Split_Names (Name, xmlname)
AS
(
SELECT
Name,
CONVERT(XML,'<Names><name>'
+ REPLACE(Name,'-', '</name><name>') + '</name></Names>') AS xmlname
FROM #t
)
SELECT
xmlname.value('/Names[1]/name[1]','varchar(100)') AS first_name,
xmlname.value('/Names[1]/name[2]','varchar(100)') AS last_name,
xmlname.value('/Names[1]/name[3]','varchar(100)') AS third_name --You can add as you want
FROM Split_Names

SQL - advice on grouping

SQL Server 2005. I am not after a coded answer here (although it would be nice). I'm really after advice on the best way forward to get the result I need. I have some knowledge of pivot/unpivot/cte//rownumber and dynamic queries but cannot get my head around this particular problem! An example of the data follows. Note: The occurrence of type,location,name and description can be none to many.
drop table #temp
create table #temp
(
event int,
type varchar(20),
locations varchar(20),
name varchar(30),
description varchar(50)
)
insert into #temp values (1,'support','r1','fred','desc 1')
insert into #temp values (1,'support','r1','fred','desc 2')
insert into #temp values (1,'support','r1','fred','desc 3')
insert into #temp values (1,'support','r1','jim','desc 1')
insert into #temp values (1,'support','r1','jim','desc 2')
insert into #temp values (1,'support','r1','jim','desc 3')
insert into #temp values (1,'support','r2','fred','desc 1')
insert into #temp values (1,'support','r2','fred','desc 2')
insert into #temp values (1,'support','r2','fred','desc 3')
insert into #temp values (1,'support','r2','jim','desc 1')
insert into #temp values (1,'support','r2','jim','desc 2')
insert into #temp values (1,'support','r2','jim','desc 3')
insert into #temp values (1,'work','r1','fred','desc 1')
insert into #temp values (1,'work','r1','fred','desc 2')
insert into #temp values (1,'work','r1','fred','desc 3')
insert into #temp values (1,'work','r1','jim','desc 1')
insert into #temp values (1,'work','r1','jim','desc 2')
insert into #temp values (1,'work','r1','jim','desc 3')
insert into #temp values (1,'work','r2','fred','desc 1')
insert into #temp values (1,'work','r2','fred','desc 2')
insert into #temp values (1,'work','r2','fred','desc 3')
insert into #temp values (1,'work','r2','jim','desc 1')
insert into #temp values (1,'work','r2','jim','desc 2')
insert into #temp values (1,'work','r2','jim','desc 3')
select * from #temp
The result I am after is this ..
1,support;work,r1;r2,fred;jim,desc1;desc2;desc3
Your goal seem to select all distinct value of all columns, then Concatenate into one string. And you only need advice, so I recommend you go here: multiple rows into a single row
It seem that you need more help:
select distinct
stuff((SELECT distinct'; ' + type-- as type
FROM #temp
--order by type
FOR XML PATH('')),1,1,'')
+ (SELECT distinct'; ' + locations
FROM #temp
FOR XML PATH(''))
+ (SELECT distinct'; ' + name
FROM #temp
FOR XML PATH(''))
+ (SELECT distinct'; ' + description
FROM #temp
FOR XML PATH(''))
from #temp;
If you need 4 columns, then change + (SELECT to , stuff((SELECT
The query is just that simple: get distinct of one column, change into string, then concatenate + string of (next column)...
This is slightly unrelated, but when inserting data like this it would be easier (for you) to do it like this (also, try to get into the habit of naming the fields you are inserting into);
INSERT INTO #temp (event, type, locations, name, description)
VALUES (1,'support','r1','fred','desc 1')
,(1,'support','r1','fred','desc 2')
,(1,'support','r1','fred','desc 3')
,(1,'support','r1','jim','desc 1')
,(1,'support','r1','jim','desc 2')
Please don't up-vote this version! All up-votes should go to the solution above! The code below is simply for completeness. This shows the syntax for organising the data into separate columns based on the answer from #NayruLove
SELECT distinct x.event,
stuff((SELECT distinct'; ' + t.type
FROM #temp t
where t.event = x.event
FOR XML PATH('')),1,1,'') as type
, stuff((SELECT distinct'; ' + locations
FROM #temp t
where t.event= x.event
FOR XML PATH('')),1,1,'') as room
, stuff((SELECT distinct'; ' + name
FROM #temp t
where t.event = x.event
FOR XML PATH('')),1,1,'') as name
, stuff((SELECT distinct'; ' + description
FROM #temp t
where t.event = x.event
FOR XML PATH('')),1,1,'') as description
from #temp x
group by x.event

Can a Pivot table be used with a unknown number of columns?

If I have a team table with a unknown amount of members, is there a way to make the pivot query dynamic?
create table #t (
team varchar (20), member varchar (20)
)
insert into #t values ('ERP', 'Jack')
insert into #t values ('ERP', 'John')
insert into #t values ('ERP', 'Mary')
insert into #t values ('ERP', 'Tim')
insert into #t values ('CRM', 'Robert')
insert into #t values ('CRM', 'Diana')
select * from #t
select team, [1] as teamMember1, /* 1st select */
[2] as teamMember2, [3] as teamMember3
from
(select team , member, row_number () /* 3rd select */
over (partition by team order by team) as rownum
from #t) a
pivot (max(member) for rownum in ([1], [2], [3])) as pvt
drop table #t
Why yes, yes there is. Here's a script I cooked up years ago for a similar problem that was ultimately solved by giving the user Excel and washing my hands of it. I apologize it's not configured with your example data, but hopefully it's easy to follow.
Hope that helps,
John
--------------START QUERY--------------
-- Example Table
CREATE TABLE #glbTestTable
(
ProviderID INT,
Total INT,
PaymentDate SMALLDATETIME
)
--So the dates insert properly
SET DATEFORMAT dmy
-- Populate Example Table
INSERT INTO #glbTestTable VALUES (232, 12200, '12/01/09')
INSERT INTO #glbTestTable VALUES (456, 10200, '12/01/09')
INSERT INTO #glbTestTable VALUES (563, 11899, '02/03/09')
INSERT INTO #glbTestTable VALUES (221, 5239, '13/04/09')
INSERT INTO #glbTestTable VALUES (987, 7899, '02/03/09')
INSERT INTO #glbTestTable VALUES (1, 1234, '02/08/09')
INSERT INTO #glbTestTable VALUES (2, 4321, '02/07/09')
INSERT INTO #glbTestTable VALUES (3, 5555, '02/06/09')
-- Raw Output
SELECT *
FROM #glbTestTable
-- Build Query for Pivot --
DECLARE #pvtColumns VARCHAR(MAX)
SET #pvtColumns = ''
-- Grab up to the first 1023 "Columns" that we want to use in Pivot Table.
-- Tables can only have 1024 columns at a maximum
SELECT TOP 1023 #pvtColumns = #pvtColumns + '[' + CONVERT(VARCHAR, PaymentDate, 103) + '], '
FROM (SELECT DISTINCT PaymentDate FROM #glbTestTable) t_distFP
-- Create PivotTable Query
DECLARE #myQuery VARCHAR(MAX)
SET #myQuery = '
SELECT ProviderID, ' + LEFT(#pvtColumns, LEN(#pvtColumns) - 1) + '
FROM (SELECT ProviderID, PaymentDate, Total
FROM #glbTestTable) AS SourceTable
PIVOT
(
SUM(Total)
FOR PaymentDate IN (' + LEFT(#pvtColumns, LEN(#pvtColumns) - 1) + ')
) AS PivotTable'
-- Run the Pivot Query
EXEC(#myQuery)
-- Cleanup
DROP TABLE #glbTestTable
---------------END QUERY---------------

I have a SQL table with multiple rows that I want into one row with multiple columns

I have a SQL table that has mulitiple rows of data for a user. I want to query that data and return one row for each user. So I want to take the multiple rows and combine them into one row with multiple columns. Is this possible?
Here is what I currently have
UserID Value
8111 396285
8111 812045789854
8111 Secretary
Here is what I am after
UserID Column1 Column2 Column3
8111 396285 812045789854 Secretary
You can use the PIVOT function to get the result. I used the row_number() function to generate the values that will be converted to columns.
If you know how many values you will have ahead of time, then you can hard-code the query:
select userid, Col1, Col2, Col3
from
(
select userid, value,
'Col'+cast(row_number() over(partition by userid
order by (select 1)) as varchar(10)) rn
from yt
) d
pivot
(
max(value)
for rn in (Col1, Col2, Col3)
) piv;
See SQL Fiddle with Demo.
If you have an unknown number of values, then you can use dynamic SQL:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME('Col'+cast(row_number() over(partition by userid
order by (select 1)) as varchar(10)))
from yt
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT userid,' + #cols + '
from
(
select userid, value,
''Col''+cast(row_number() over(partition by userid
order by (select 1)) as varchar(10)) rn
from yt
) x
pivot
(
max(value)
for rn in (' + #cols + ')
) p '
execute(#query);
See SQL Fiddle with Demo. Both give the result:
| USERID | COL1 | COL2 | COL3 |
----------------------------------------------
| 8111 | 396285 | 812045789854 | Secretary |
If you cannot or don't want to use PIVOT/UNPIVOT another option would be to join the columns one by one to the users:
DECLARE #Users TABLE(
UserID int NOT NULL
)
INSERT INTO #Users (UserID) VALUES (1)
INSERT INTO #Users (UserID) VALUES (2)
INSERT INTO #Users (UserID) VALUES (3)
DECLARE #AnyTable TABLE(
UserID int NOT NULL,
FieldNo int NOT NULL,
Value varchar(50) NULL
)
INSERT INTO #AnyTable (UserID, FieldNo, Value) VALUES (1, 1, 'abc')
INSERT INTO #AnyTable (UserID, FieldNo, Value) VALUES (1, 2, 'def')
INSERT INTO #AnyTable (UserID, FieldNo, Value) VALUES (1, 3, 'ghi')
INSERT INTO #AnyTable (UserID, FieldNo, Value) VALUES (2, 1, '123')
INSERT INTO #AnyTable (UserID, FieldNo, Value) VALUES (2, 3, '789')
SELECT u.UserID,
col1.Value as Column1,
col2.Value as Column2,
col3.Value as Column3
FROM #Users u
LEFT JOIN #AnyTable col1
ON col1.UserID = u.UserID
AND col1.FieldNo = 1
LEFT JOIN #AnyTable col2
ON col2.UserID = u.UserID
AND col2.FieldNo = 2
LEFT JOIN #AnyTable col3
ON col3.UserID = u.UserID
AND col3.FieldNo = 3
The result would be:
UserID Column1 Column2 Column3
1 abc def ghi
2 123 NULL 789
3 NULL NULL NULL