simple yet twisted SQL query - sql

I have a table say like
X Y
1 3
2 4
Now when a view table in SQL it would show
A1 A2
1 3
2 4
But I want output to be like
A1 A2
X Y
1 3
2 4
Is it possible to do so? Please let me know if I am able to point out my problem.

DECLARE #ColNames VARCHAR(100),#Query VARCHAR(100) = ''
CREATE TABLE Tbl1 (X INT, Y INT) CREATE TABLE Tbl2 (A1 VARCHAR(10), A2 VARCHAR(10)) INSERT INTO Tbl1 (X , Y ) SELECT 1,3 UNION ALL SELECT 2,4
SELECT DISTINCT #ColNames = STUFF( ( SELECT ',' + Col.name + ''
FROM SYS.COLUMNS Col WHERE OBJECT_NAME(Col.OBJECT_ID) = 'Tbl1' FOR XML PATH('') ), 1,1,'') SET #Query = 'SELECT ''' + REPLACE(#ColNames,',',''',''') + ''''
INSERT INTO Tbl2 (A1 , A2 )
EXEC (#Query)
INSERT INTO Tbl2 (A1 , A2 )
SELECT 1,3 UNION ALL
SELECT 2,4
SELECT * FROM Tbl2

Related

How to get below query

I have a table with one field name as City.
Below are the data.
City
--------
A
B
C
D
E
F
G
H
Output will be as Column as well
Write a query or stored procedure or function?
If a pass 2, the query result will be below
Col1 Col2
A B
C D
E F
G H
If a pass 3, the query result will be below
Col1 Col2 Col3
A B C
D E F
G H
If a pass 4, the query result will be below
Col1 Col2 Col3 Clo4
A B C D
E F G H
--Here script for creating and adding data into temp table
create table #Cities( City varchar(max) )
insert into #Cities values
( 'A' ),
( 'B' ),
( 'C' ),
( 'D' ),
( 'E' ),
( 'F' ),
( 'G' ),
( 'H' )
declare #what_I_pass as int = 2; -- Here pass the number you want.
with Q1 as
(
select *, ROW_NUMBER() over (order by City) - 1 as n
from #Cities
),
Q2 as
(
select City, n / #what_I_pass as rn, n % #what_I_pass as cn
from Q1
)
select (stuff((select ' ' + City from Q2 as q where q.rn = Q2.rn order by cn for xml path('')), 1, 1, '')) as Result
from Q2
group by rn
order by rn
This would do:
declare #Cols int = 3 -- We define here how many output columns we want: 1, 2, 3, ... up to 10
create table #Cities( City varchar(max) )
insert into #Cities values
( 'A' ),
( 'B' ),
( 'C' ),
( 'D' ),
( 'E' ),
( 'F' ),
( 'G' ),
( 'H' )
;
with Cities as (
select City,
row_number() over (order by City) - 1 as Num
from #Cities
)
select Col1.City as Col1, Col2.City as Col2, Col3.City as Col3, Col4.City as Col4, Col5.City as Col5, Col6.City as Col6, Col7.City as Col7, Col8.City as Col8, Col9.City as Col9, Col10.City as Col10
from Cities as Rows
left join Cities as Col1 on 0 < #Cols and Col1.Num = Rows.Num * #Cols + 0
left join Cities as Col2 on 1 < #Cols and Col2.Num = Rows.Num * #Cols + 1
left join Cities as Col3 on 2 < #Cols and Col3.Num = Rows.Num * #Cols + 2
left join Cities as Col4 on 3 < #Cols and Col4.Num = Rows.Num * #Cols + 3
left join Cities as Col5 on 4 < #Cols and Col5.Num = Rows.Num * #Cols + 4
left join Cities as Col6 on 5 < #Cols and Col6.Num = Rows.Num * #Cols + 5
left join Cities as Col7 on 6 < #Cols and Col7.Num = Rows.Num * #Cols + 6
left join Cities as Col8 on 7 < #Cols and Col8.Num = Rows.Num * #Cols + 7
left join Cities as Col9 on 8 < #Cols and Col9.Num = Rows.Num * #Cols + 8
left join Cities as Col10 on 9 < #Cols and Col10.Num = Rows.Num * #Cols + 9
where Rows.Num <= (select max(Num) from Cities) / #Cols
drop table #Cities
Result for an input of 3 :
Col1 Col2 Col3 Col4 Col5 Col6 Col7 Col8 Col9 Col10
A B C NULL NULL NULL NULL NULL NULL NULL
D E F NULL NULL NULL NULL NULL NULL NULL
G H NULL NULL NULL NULL NULL NULL NULL NULL
PS: To avoid using dynamic SQL this query always returns a fixed number of 10 columns, but just the desired columns are filled. Now your presentation layer only needs to hide the unwanted empty columns.
Try below query:
--Here script for creating and adding data into temp table
declare #tbl table ( City varchar(max) )
insert into #tbl values
( 'A' ),
( 'B' ),
( 'C' ),
( 'D' ),
( 'E' ),
( 'F' ),
( 'G' ),
( 'H' )
declare #howManyCols int = 3;
;with cte as (
select City, grp,
row_number() over (partition by grp order by City) rn
from (
select *,
(row_number() over (order by City) - 1) % #howManyCols + 1 grp
from #tbl
) a
)
-- this query can be generated by dynamic SQL, because you can see pattern in following lft join's
select c1.City, c2.City, c3.City
from cte c1
left join cte c2 on c1.grp = c2.grp - 1 and c1.rn = c2.rn
left join cte c3 on c2.grp = c3.grp - 1 and c2.rn = c3.rn
where c1.grp = 1
For number of columns equal to three you get:
Try this script,
declare #flg int=3--test with 1,2,3,4 ...
create table #temp(id int identity(1,1),col varchar(10))
insert into #temp values ('A'),('B'),('C'),('D'),('E'),('F'),('G'),('H')
create table #temp1(id int ,col varchar(10),flag int,rownum int)
declare #PvtCol varchar(500)=''
declare #Headcol varchar(500)
declare #Sql nvarchar(500)
WITH CTE
AS (SELECT id,
col,
CASE
WHEN(id % #flg) = 0
THEN #flg
ELSE(id % #flg)
END flag
FROM #temp),
CTE1
AS (SELECT *,
ROW_NUMBER() OVER(PARTITION BY flag
ORDER BY id) rownum
FROM cte)
INSERT INTO #temp1
(id,
col,
flag,
rownum
)
SELECT id,
col,
flag,
rownum
FROM cte1;
SELECT #PvtCol = COALESCE(#PvtCol + ', ' + QUOTENAME(rownum), QUOTENAME(rownum)),
#Headcol = COALESCE(#Headcol + ', ' + QUOTENAME(rownum) + ' as ' + 'col', QUOTENAME(rownum) + ' as ' + 'col') + CAST(rownum AS VARCHAR)
FROM #temp1
WHERE flag = 1;
SET #PvtCol = STUFF(#PvtCol, 1, 1, '');
SELECT #PvtCol,
#Headcol;
SET #Sql = 'select flag,' + #Headcol + ' from
(
select flag, col,rownum from #temp1
)src
pivot(max(col) for rownum in(' + #PvtCol + ')) as pvt';
PRINT #Sql;
EXECUTE sp_executesql
#Sql;
DROP TABLE #temp, #temp1;

pivot in sql server 2012 with uniqeness

if i have a table like given below.
declare #mytble table
(
orders int,
product varchar (50),
quantity int
)
INSERT #mytble
SELECT 100,'CUP','1' UNION ALL
SELECT 100, 'PLATE',2 UNION ALL
SELECT 101,'CUP','1' UNION ALL
SELECT 102,'CUP','2' UNION ALL
SELECT 103, 'CUP',1 UNION ALL
SELECT 103,'PLATE','3' UNION ALL
SELECT 103,'GLASS','1'
SELECT * FROM #mytble
will it be possible to get output like this.
any suggestion please.
With some dynamic SQL and Dense_Rank() function
Declare #SQL varchar(max)
Select #SQL = Stuff((Select Distinct ',' + QuoteName(concat('Product',Dense_Rank() over (Order By Product)))
+ ',' + QuoteName(concat('Quantity',Dense_Rank() over (Order By Product)))
From myTable For XML Path('')),1,1,'')
Select #SQL = 'Select Orders,' + #SQL + '
From (
Select Orders,Item=concat(''Product'',Dense_Rank() over (Order By Product)),Val=cast(Product as varchar(max)) From myTable
Union All
Select Orders,Item=concat(''Quantity'',Dense_Rank() over (Order By Product)),Val=cast(Quantity as varchar(max)) From myTable
) A
Pivot (max(Val) For Item in (' + #SQL + ') ) p'
Exec(#SQL);
Returns
Orders Product1 Quantity1 Product2 Quantity2 Product3 Quantity3
100 CUP 1 NULL NULL PLATE 2
101 CUP 1 NULL NULL NULL NULL
102 CUP 2 NULL NULL NULL NULL
103 CUP 1 GLASS 1 PLATE 3

SQL PIVOT result set [duplicate]

This question already has answers here:
SQL Server dynamic PIVOT query?
(9 answers)
Closed 8 years ago.
Looking for help with pivoting a result set as I'm very new to it.
Here I have test data inserted into a table.
CREATE TABLE #temp (procCode int, member_id varchar(10))
INSERT INTO #temp(procCode,member_id)
SELECT 90658,'jjjj'
UNION all
SELECT 90658,'k'
UNION all
SELECT 90658,'jjjkk'
UNION all
SELECT 90658,'jjjj'
UNION all
SELECT 90658,'k'
UNION all
SELECT 90658,'jjjkk'
UNION all
SELECT 90658,'jjjj'
UNION all
SELECT 90658,'k'
UNION all
SELECT 90649,'jjjj'
UNION all
SELECT 90649,'k'
UNION all
SELECT 906,'jjjj'
UNION all
SELECT 906,'jjjj'
select
member_id,procCode, COUNT(*) as countProcCode
FROM #temp
GROUP BY member_id,procCode
This right now outputs data like this:
member_id procCode CountProcCode
jjjj 906 2
jjjj 90649 1
jjjkk 90658 2
k 90649 1
jjjj 90658 3
k 90658 3
How I need it to display is like this:
member_id Count906 count90649 count90658
jjjj 2 1 3
k 0 1 3
jjjkk 0 0 2
Any help is greatly appreciated.
There are more than just these procCodes and member_id so I couldn't really say where member_id in (506,50658,50649) as there are additional ones that could appear.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.procCode)
FROM #temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT member_id, ' + #cols + ' from
(
select member_id, member_id as b
, procCode
from #temp
) x
pivot
(
count(b)
for procCode in (' + #cols + ')
) p '
execute(#query)
drop table #temp
Results
member_id 906 90649 90658
jjjj 2 1 3
jjjkk 0 0 2
k 0 1 3
Recomended reading

SQL complex dynamic Pivoting 2

Hi I am trying in SQL Server the pivoting for the following table
REFID | COL1 | COL2 | Sequence
1 abc cde 1
1 lmn rst 2
1 kna asg 3
2 als zkd 2
2 zpk lad 1
I want the output as
REFID | 1COL1 | 2COL1 | 3COL1 |1COL2|2COL2|3COL2
1 abc lmn kna cde rst asg
2 zpk als null lad zkd null
The number of columns in the original table are known but the number of rows are not known. Can any one help
If you want to include the sequence number as part of your column names, then you will still need to unpivot your col1 and col2 columns first, then apply the pivot. The difference is that you will concatenate the sequence number to your column names created during the unpivot process.
For a known number of values the query would be:
select REFID,
[1col1], [2col1], [3col1],
[1col2], [2col2], [3col2]
from
(
select REFID,
col = cast(Sequence as varchar(10))+ col, value
from yourtable
cross apply
(
select 'COL1', col1 union all
select 'COL2', col2
) c (col, value)
) d
pivot
(
max(value)
for col in ([1col1], [2col1], [3col1],
[1col2], [2col2], [3col2])
) piv
order by refid;
Then if you have an unknown number the dynamic SQL version will be:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(cast(Sequence as varchar(10))+ col)
from yourtable
cross apply
(
select 'Col1', 1 union all
select 'Col2', 2
) c(col, so)
group by Sequence, col, so
order by so, sequence
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT refid, ' + #cols + '
from
(
select REFID,
col = cast(Sequence as varchar(10))+ col, value
from yourtable
cross apply
(
select ''COL1'', col1 union all
select ''COL2'', col2
) c (col, value)
) x
pivot
(
max(value)
for col in (' + #cols + ')
) p
order by refid'
execute sp_executesql #query;

SQL count ids in fields

I have a table contains IDs in field. It looks like:
FieldName
-------------------------
1,8,2,3,4,10,5,9,6,7
-------------------------
1,8
-------------------------
1,8
I need to count these IDs to get result:
ID | Count
---|------
1 | 3
8 | 3
2 | 1
3 | 1
Any ideas?
Thanks!
Try this :
Declare #demo table(FieldName varchar(100))
insert into #demo values('1,8,2,3,4,10,5,9,6,7')
insert into #demo values('1,8')
insert into #demo values('1,8')
select ID, COUNT(id) ID_count from
(SELECT
CAST(Split.a.value('.', 'VARCHAR(100)') AS INT) AS ID
FROM
(
SELECT CAST ('<M>' + REPLACE(FieldName, ',', '</M><M>') + '</M>' AS XML) AS ID
FROM #demo
) AS A CROSS APPLY ID.nodes ('/M') AS Split(a)) q1
group by ID
I like Devart's answer because of the faster execution. Here is a modified earlier answer to suite your need :
Declare #col varchar(200)
SELECT
#col=(
SELECT FieldName + ','
FROM #demo c
FOR XML PATH('')
);
;with demo as(
select cast(substring(#col,1,charindex(',',#col,1)-1) AS INT) cou,charindex(',',#col,1) pos
union all
select cast(substring(#col,pos+1,charindex(',',#col,pos+1)-pos-1)AS INT) cou,charindex(',',#col,pos+1) pos
from demo where pos<LEN(#col))
select cou ID, COUNT(cou) id_count from demo
group by cou
Try this one -
Query:
SET NOCOUNT ON;
DECLARE #temp TABLE (txt VARCHAR(8000))
INSERT INTO #temp (txt)
VALUES ('1,8,2,3,4,10,5,9,6,7'), ('1,8'), ('1,8')
SELECT
t.ID
, [Count] = COUNT(1)
FROM (
SELECT
ID =
SUBSTRING(
t.string
, number + 1
, ABS(CHARINDEX(',', t.string, number + 1) - number - 1)
)
FROM (
SELECT string = (
SELECT ',' + txt
FROM #temp
FOR XML PATH(N''), TYPE, ROOT).value(N'root[1]', N'NVARCHAR(MAX)')
) t
CROSS JOIN [master].dbo.spt_values n
WHERE [type] = 'p'
AND number <= LEN(t.string) - 1
AND SUBSTRING(t.string, number, 1) = ','
) t
GROUP BY t.ID
ORDER BY [Count] DESC
Output:
ID Count
----- -----------
1 3
8 3
9 1
10 1
2 1
3 1
4 1
5 1
6 1
7 1
Query cost: