Selecting 3 rows into 3 columns in sql server - sql

I am trying to select the 3 rows into 3 columns, but i get NULL values.
Here is my code so far:
SELECT * FROM
(
SELECT t_k
FROM m_t_k
WHERE p_id = 5 and t_k_id in (1,2,7)
) src
PIVOT(
MAX()
for t_k in ([1],[2],[3])
) piv
this is the result of the query without the PIVOT
and i want those rows to be on 3 columns

You could use ROW_NUMBER and a Cross Tab to achieve this. This is a bit of a guess, based on the query and image we have though, so it is untested:
SELECT MAX(CASE WHEN RN = 1 THEN sq.term_key END) AS term_key1,
MAX(CASE WHEN RN = 2 THEN sq.term_key END) AS term_key2,
MAX(CASE WHEN RN = 3 THEN sq.term_key END) AS term_key3
FROM (SELECT term_key,
ROW_NUMBER() OVER (ORDER BY term_key) AS RN
FROM mpos_term_key
WHERE profile_id = 5
AND term_keys_type_id IN (1, 2, 7)) sq;

Related

sql transformation - rows to column

i have been trying to solve this one image
my initial idea is like this
select name,
CASE
when count(name) = 1 then get first distinct value
when count(name) = 2 then get first distinct value
else get first distinct value
END as val1,
CASE
when count(name) = 1 then null
when count(name) = 2 then get second distinct value
else get second distinct value
END as val2,
CASE
when count(name) = 1 then null
when count(name) = 2 then null
else get third distinct value
END as val3
into desired_table
from source_table
group by name
is my attempt feasible? if so, how do i access the first, second and third distinct values?
use pivot . Your output table was incorrect. The correct form is available in db<>fiddle.
select name,x as value1,y as value2,z as value3
from
(
select *
from t1
) as SourceTable
pivot
(
max(value) for value in(x,y,z)
) as PivotTable
demo in db<>fiddle
You can use conditional aggregation along with row_number():
select name,
max(case when seqnum = 1 then value end) as value_1,
max(case when seqnum = 2 then value end) as value_2,
max(case when seqnum = 3 then value end) as value_3
into desired_table
from (select s.*,
row_number() over (partition by name order by value) as seqnum
from source_table s
) s
group by name;

SQL Server Sorting Multiple Values from different columns and reassign them based on ascending value

I have a select statement that brings the values of 5 different columns.
SELECT TOP 1 digit1, digit2, digit3, digit4, digit5 FROM myTable
The result is "25, 36, 1, 63, 12".
My question is, how do I sort these numbers in Ascending order and reassign them to their respectively Ascending columns?
I.E: digit1 = 1, digit2 = 12, digit3 = 25, digit4 = 36, digit5 = 63.
Thanks in advance for the help.
You can do an UNPIVOT followed by a PIVOT
Example
Select *
From (
Select Item = concat('digit',Row_NUmber() over (Order by Value))
,Value
From (Select top 1 * from YourTable) A
UnPivot ( Value for Digits in (digit1,digit2,digit3,digit4,digit5) ) U
) A
Pivot (max(Value) for Item in (digit1,digit2,digit3,digit4,digit5) ) P
Returns
digit1 digit2 digit3 digit4 digit5
1 12 25 36 63
I would use apply:
select v.*
from (select top 1 digit1, digit2, digit3, digit4, digit5 FROM myTable
) t cross apply
(select max(case when seqnum = 1 then digit end) as digit1,
max(case when seqnum = 2 then digit end) as digit2,
max(case when seqnum = 3 then digit end) as digit3,
max(case when seqnum = 4 then digit end) as digit4,
max(case when seqnum = 5 then digit end) as digit5
from (select v.digit, row_number() over (order by v.digit) as seqnum
from (values (digit1), (digit2), (digit3), (digit4), (digit5)
) v(digit)
) v
) v;
If you want to order the results by multiple values, you can use the following syntax.
SELECT TOP 1 digit1, digit2, digit3, digit4, digit5
FROM myTable
ORDER BY digit1, digit2, digit3, digit4, digit5
If the values need manipulation, you may need to create a UDF/CTE or inline expression to determine the 'value' of the columns to order them. Without a full working example (A SQLFiddle would be helpful), it is difficult to be sure.
Using a CTE should allow this to be simplified to something like this. I am assuming that you need this for multiple rows, but simplifying it to a single row is easier than expanding a solution to multiple rows
WITH MyData as (
SELECT ID, digit1 as Digit FROM myTable
UNION ALL
SELECT ID, digit2 FROM myTable
UNION ALL
SELECT ID, digit3 FROM myTable
UNION ALL
SELECT ID, digit4 FROM myTable
UNION ALL
SELECT ID, digit5 FROM myTable
)
SELECT ID, Digit
FROM MyData
ORDER BY ID, Digit
Your data is now in order. A simple PIVOT will give you the output you are looking for.

Find the latest 3 records with the same status

I need to find the latest 3 records for each user that has a particular status on 'Fail'. At first it seems easy but I just can't seem to get it right.
So in a table of:
ID Date Status
1 2017-01-01 Fail
1 2017-01-02 Fail
1 2017-02-04 Fail
1 2015-03-21 Pass
1 2014-02-19 Fail
1 2016-10-23 Pass
2 2017-01-01 Fail
2 2017-01-02 Pass
2 2017-02-04 Fail
2 2016-10-23 Fail
I would expect ID 1 to be returned as the most recent 3 records are fails, but not ID 2, as they have a pass within their three fails. Each user may have any number of Pass and Fail records. There are thousands of different IDs
So far I've tried a CTE with ROW_NUMBER() to order the attempts but can't think of a way to ensure that the latest three results all have the same status of Fail.
Expected Results
ID Latest Fail Date Count
1 2017-02-04 3
Maybe try something like this:
WITH cte
AS
(
SELECT id,
date,
status,
ROW_NUMBER () OVER (PARTITION BY id ORDER BY date DESC) row
FROM #table
),cte2
AS
(
SELECT id, max(date) as date, count(*) AS count
FROM cte
WHERE status = 'fail'
AND row <= 3
GROUP BY id
)
SELECT id,
date AS latest_fail,
count
FROM cte2
WHERE count = 3
Check This.
Demo : Here
with CTE as
(
select *,ROW_NUMBER () over( partition by id order by date desc) rnk
from temp
where Status ='Fail'
)
select top 1 ID,max(DATE) as Latest_Fail_Date ,COUNT(rnk) as count
from CTE where rnk <=3
group by ID
Ouptut :
I think you can do this using cross apply:
select i.id
from (select distinct id from t) i cross apply
(select sum(case when t.status = 'Fail' then 1 else 0 end) as numFails
from (select top 3 t.*
from t
where t.id = i.id
order by date desc
) ti
) ti
where numFails = 3;
Note: You probably have a table with all the ids. If so, you an use that instead of the select distinct subquery.
Or, similarly:
select i.id
from (select distinct id from t) i cross apply
(select top 3 t.*
from t
where t.id = i.id
order by date desc
) ti
group by i.id
having min(ti.status) = 'Fail' and max(ti.status) = 'Fail' and
count(*) = 3;
Here you go:
declare #numOfTries int = 3;
with fails_nums as
(
select *, row_number() over (partition by ID order by [Date] desc) as rn
from #fails
)
select ID, max([Date]) [Date], count(*) as [count]
from fails_nums fn1
where fn1.rn <= #numOftries
group by ID
having count(case when [Status]='Fail' then [Status] end) = #numOfTries
Example here

Divide N rows to N columns

I have a result set which provide me 2 columns named Sequence and CorrectAns and it contains N rows(100 rows right now to be specific).
Now what I want is to divide these 100 rows to N columns(right now into 4 columns).
So, how to do that? Any help would be appreciated.
This is the result that i am getting. Now what I want is something like this:
Seq ColA Seq ColB Seq ColC Seq ColD
1 C 4 A 7 C 10 D
2 A 5 C 8 A 11 C
3 A 6 A 9 C 12 A
and so on.
Hope this helps
What you want is to pivot your data. Aside from the PIVOT command, one way to do that is to use conditional aggregation:
SQL Fiddle
;WITH Cte AS(
SELECT *,
grp = (ROW_NUMBER() OVER(ORDER BY Seq) -1) %
(SELECT CEILING(COUNT(*) / (4 * 1.0)) FROM tbl)
FROM tbl
),
CteFinal AS(
SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY grp ORDER BY Seq)
FROM Cte
)
SELECT
SeqA = MAX(CASE WHEN rn = 1 THEN Seq END),
ColA = MAX(CASE WHEN rn = 1 THEN CorrectAns END),
SeqB = MAX(CASE WHEN rn = 2 THEN Seq END),
ColB = MAX(CASE WHEN rn = 2 THEN CorrectAns END),
SeqC = MAX(CASE WHEN rn = 3 THEN Seq END),
ColC = MAX(CASE WHEN rn = 3 THEN CorrectAns END),
SeqD = MAX(CASE WHEN rn = 4 THEN Seq END),
ColD = MAX(CASE WHEN rn = 4 THEN CorrectAns END)
FROM CteFinal
GROUP BY grp
use the following query,
SELECT *
FROM (
SELECT
Seq, CorrectAns,
gro
FROM your_table
) as t
PIVOT
(
SUM(gro)
FOR CorrectAns IN (A,B,C,D....)
)AS pvt
If i understood what you said clearly, you can put your result set in an Array.
and then use this SQL QUERY
ALTER TABLE table_name
ADD column_name datatype
Example :
ALTER TABLE customer ADD name VARCHAR(Max);
You can specified a loop from the 0 to size of the Array and put that query inside the loop.
Edit :
Ok, I think it should be something like this;
DECLARE #cnt INT = 0;
DECLARE #str = "";
WHILE #cnt < 100000
BEGIN
SET #cnt = #cnt + 1;
SET #str='yourRowName';
ALTER TABLE yourTableName
ADD str datatype
END;
Take a look at this.
http://www.techonthenet.com/sql_server/loops/for_loop.php

How to create "subsets" as a result from a column in SQL

Let's suppose that I've got as a result from one query the next set of values of one column:
Value
1 A
2 B
3 C
4 D
5 E
6 F
7 G
8 H
9 I
10 J
Now, I would like to see this information with another order, establishing a limit to the number of values of every single subset. Now suppose that I choose 3 as a limit,the information will be given like this (one column for all the subsets):
Values
1 A, B, C
2 D, E, F
3 G, H, I
4 J,
Obviously, the last row will contain the remaining values when their number is smaller than the limit established.
Is it possible to perform a query like this in SQL?
What about if the limit is dynamic?. It can be chosen randomly.
create table dee_t (id int identity(1,1),name varchar(10))
insert into dee_t values ('A'),('B'),('c'),('D'),('E'),('F'),('g'),('H'),('I'),('J')
;with cte as
(
select (id-1)/3 +1 rno ,* from dee_t
) select rno ,
(select name+',' from cte where rno = c.rno for xml path('') )
from cte c group by rno
You can do this by using few calculations with row_number, like this:
select
GRP,
max(case when RN = 1 then Value end),
max(case when RN = 2 then Value end),
max(case when RN = 0 then Value end)
from (
select
row_number() over (order by Value) % 3 as RN,
(row_number() over (order by Value)+2) / 3 as GRP,
Value
from Table1
) X
group by GRP
The first row_number creates numbers for the columns (1,2,0,1,2,0...) and the second one creates numbers for the rows (1,1,1,2...). Those are then used to group the values into correct place using case, but you can also use pivot instead of it if you like it more.
If you want them into same column, of course just concatenate the cases instead of selecting them on different columns, but beware of nulls.
Example in SQL Fiddle
Thanks a lot for all your reply. Finally I've got a Solution with the help of Rajen Singh
This is the code than can be used:
WITH CTE_0 AS
(
SELECT DISTINCT column_A_VALUE AS id
FROM Table
WHERE column_A_VALUE IS NOT NULL
), CTE_1 AS
(
SELECT ROW_NUMBER() OVER (ORDER BY id) RN, id
FROM CTE_0
), CTE_2 AS
(
SELECT RN%30 GROUP, ID
FROM CTE_1
)SELECT STUFF(( SELECT ','''+CAST(ID AS NVARCHAR(20))+''''
FROM CTE_2
WHERE GROUP = A.GROUP
FOR XML PATH('')),1,1,'') IDS
FROM CTE_2 A
GROUP BY GROUP