SQL server query: only certain column values into row, iterating - sql

I need to build a SQL query in SQL SERVER 10.50.1600.1. I have the following model situation:
id1 | value1
id1 | value2
id2 | value1
id3 | value1
id3 | value2
...
and would like to end up in a situation as
id1 | value1 | value2
id2 | value1 | null
id3 | value1 | value2
...
I only know that for each id[n] there are at most 4 values recorded.
EDIT: I know there are at most 4 values for each, but they could be anything. They can be any number included in [0, 9000] or a string (about 10 possibilities). My bad, I didn't explain well.

If you know the values in advance, and the values are unique per ID (as they seem to be from your question statement) it's fairly straightforward:
-- Setup
declare #a table (id nvarchar(50), value nvarchar(50))
insert #a(id, value) values
('id1', 'value1'),
('id1', 'value2'),
('id2', 'value1'),
('id3', 'value1'),
('id3', 'value2')
;
SELECT id,
MAX(CASE value WHEN 'value1' THEN value END) AS value1,
MAX(CASE value WHEN 'value2' THEN value END) AS value2,
MAX(CASE value WHEN 'value3' THEN value END) AS value3,
MAX(CASE value WHEN 'value4' THEN value END) AS value4
FROM #a
GROUP BY id

Below query will help you :-
declare #test table (id nvarchar(50), value nvarchar(50))
insert #test(id, value) values
('id1', 'value1'),
('id1', 'value2'),
('id1', 'value3'),
('id1', 'value4'),
('id2', 'value1'),
('id3', 'value1'),
('id3', 'value2'),
('id3', 'value3');
select ROW_NUMBER() OVER (PARTITION BY id ORDER BY id) AS ROWNUM,id,value into #t1 from #test
SELECT distinct id,
(select value from #t1 b where b.id=a.id AND b.ROWNUM=1) AS Value1,
(select value from #t1 b where b.id=a.id AND b.ROWNUM=2) AS Value2,
(select value from #t1 b where b.id=a.id AND b.ROWNUM=3) AS Value3,
(select value from #t1 b where b.id=a.id AND b.ROWNUM=4) AS Value4
FROM #t1 a
drop table #t1
Output :-
id Value1 Value2 Value3 Value4
id1 value1 value2 value3 value4
id2 value1 NULL NULL NULL
id3 value1 value2 value3 NULL

Assumtion: TABLE: table_name(id_column, value_column). With each value of id_column there are at most 4 values of value_column
Then you could use this
WITH tmp as
(SELECT
*
,ROW_NUMBER() over (PARTITION BY id_column order by value_column) rwn
FROM
table_name
)
SELECT
id_column
,MAX(CASE WHEN rwn = 1 THEN value_column END) value1
,MAX(CASE WHEN rwn = 2 THEN value_column END) value2
,MAX(CASE WHEN rwn = 3 THEN value_column END) value3
,MAX(CASE WHEN rwn = 4 THEN value_column END) value4
FROM
tmp
GROUP BY
id_column;

Related

Combining data from 2 tables and pivoting data from 1 of them

I have the current situation:
TableA
----------
SN Date OpsID
1234 2018-02-12 1
1324 2018-02-12 2
2134 2018-02-13 3
TableB
----------
Name String Number OpsID
Value1 Hello NULL 1
Value2 NULL 1111 1
Value3 Apples NULL 1
Value1 There NULL 2
Value2 NULL 2222 2
Value3 Pears NULL 2
Value1 Baby NULL 3
Value2 NULL 3333 3
Value3 Bananas NULL 3
...and the result I'm looking for is:
SN Date Value1 Value2 Value3
1234 2018-02-12 Hello 1111 Apples
1324 2018-02-12 There 2222 Pears
2134 2018-02-13 Baby 3333 Bananas
The query I ran is obviously wrong because I'm getting mostly NULL and only Value data, but here it is anyway:
SELECT SN,Date,Value1,Value2,Value3
FROM(
SELECT TableA.SN,
TableA.Date,
TableB.Name,
TableB.String,
TableB.Number
FROM TableA,TableB
WHERE
TableA.OpsID = TableB.OpsID
ORDER BY Date ASC
)Temp
PIVOT(
MAX(Value)
FOR Name in(
Value1,Value2,Value3
)
)PIV
Note that Value1 and Value3 are always VARCHAR and Value2 is always an INT
You combine String and Number into a single column in a subquery, and then pivot the values back out into their own columns like this:
SELECT SN, Date, Value1, CAST(Value2 AS INT) Value2, Value3
FROM
(
SELECT a.SN, a.Date, B.Name, ISNULL(b.String, CAST(b.Number AS VARCHAR(10))) Value
FROM TableA A
INNER JOIN TableB B ON A.OpsID = B.OpsID
)sq1
PIVOT (MAX(Value) FOR Name IN ([Value1], [Value2], [Value3]))sq2
You can do conditional aggregation :
select a.SN, a.date,
max(case when b.Name = 'Value1' then coalesce(b.String, cast(b.Number as varchar(255))) end) as Value1,
max(case when b.Name = 'Value2' then coalesce(b.String, cast(b.Number as varchar(255))) end) as Value2,
max(case when b.Name = 'Value3' then coalesce(b.String, cast(b.Number as varchar(255))) end) as Value3
from tablea a inner join
tableb b
on b.OpsID = a.OpsID
group by a.SN, a.date;

How to select a value on the first row and last on SQL?

I have a table like this:
ID | persid | value1 | value2
---+--------+---------+---------
1 | A | string1 | string2
2 | A | string3 | string4
3 | A | string5 | string6
I need to return something like this using GROUP BY:
Field1 | field2 | field3
-------+---------+----------
A | string1 | string6
I'm using SQL server 2008,
Is this possible?
I would use conditional aggregation:
select persid,
max(case when seqnum_asc = 1 then value1 end) as value1,
max(case when seqnum_desc = 1 then value2 end) as value2
from (select t.*,
row_number() over (partition by persid order by id) as seqnum_asc,
row_number() over (partition by persid order by id desc) as seqnum_desc
from t
) t
group by persid;
You can try something like this:
create table tbl (id int, persid varchar(10), value1 varchar(10), value2 varchar(10));
insert into tbl (id, persid, value1, value2) values (1, 'A', 'string1', 'string2');
insert into tbl (id, persid, value1, value2) values (2, 'A', 'string3', 'string4');
insert into tbl (id, persid, value1, value2) values (3, 'A', 'string5', 'string6');
select tbl.persid, tbl.value1, persmax.value2
from tbl
inner join tbl persmax on persmax.id = (select max(id) from tbl where persid='A')
where tbl.persid='A'
and tbl.id = (select min(id) from tbl where persid='A')
I think you can use a query like this:
select top(1) yourTable.persid field1, yourTable.value1 field2, t.value2 field3
from yourTable
cross join (
select top(1) value2
from yourTable
order by ID desc
) t
order by ID;
How about this?
select distinct a, b, c from
(select mytbl.persid as a, mytbl.value1 as b from mytbl,
(select persid, min(id) as id from mytbl group by persid) as t1
where mytbl.id = t1.id and mytbl.persid = t1.persid) as t2,
(select mytbl.persid as d, mytbl.value2 as c from mytbl,
(select persid, max(id) as id from mytbl group by persid) as t3
where mytbl.id = t3.id and mytbl.persid = t3.persid) as t4
where t2.a = t4.d

Inserting multiple rows with column into single row

I am trying to write a query to copy set of rows from one table to another table in this format
Table 1
ColumnName ColumnValue RowId
Column1 Value1 1
Column2 Value2 1
Column3 Value3 1
Column1 Value4 2
Column2 Value5 2
Column3 Value6 2
Column1 Value7 3
Column2 Value8 3
Column3 Value9 3
Table2
Column1 Column2 Column3
Value1 Value2 Value3
Value4 Value5 Value6
Value7 Value8 Value9
Here basically table 1 is input and table 2 is the output which I am trying. I used the pivot and row number but none worked.
What will be the insert query to achieve this. Here all rows of rowId 1 from table 1 will form form one row of table2.
select rowID,
max(case when columnName = 'Column1' then value else null end) as column1,
max(case when columnName = 'Column2' then value else null end) as column2,
max(case when columnName = 'Column3' then value else null end) as column3
from table1
group by rowID

Oracle query with group by and sort order with respect to key

I have values in oracle database having key values pair stored as below
KEY VALUE SortOrder REGN NO
---------------------------------------
KEY1 VALUE1 1 123
KEY2 VALUE2 2 123
KEY1 VALUE3 3 123
KEY1 VALUE4 1 456
KEY1 VALUE5 3 456
KEY1 VALUE6 2 456
KEY2 VALUE7 1 678
KEY2 VALUE8 3 678
Key 2 VALUE9 2 678
For each key I have sort order against REGN NO. Maximum three entries are allowed
for each REGN NO but it can be any key. I need to get result by grouping REGN NO for a specific key and should be order by sort order . For eg For KEY1 result looks like
REG NO OPTION1 OPTION 2 OPTION 3
------------------------------------------
123 VALUE 1 VALUE 3
456 VALUE 4 VALUE 6 VALUE 5
How can i fetch this using oracle SQL statement?
Try this:
CREATE TABLE key_value (
KEY VARCHAR2(20),
VALUE VARCHAR2(20),
SortOrder NUMBER,
REGN_NO NUMBER
);
INSERT INTO key_value VALUES ('KEY1', 'VALUE1', 1, 123);
INSERT INTO key_value VALUES ('KEY2', 'VALUE2', 2, 123);
INSERT INTO key_value VALUES ('KEY1', 'VALUE3', 3, 123);
INSERT INTO key_value VALUES ('KEY1', 'VALUE4', 1, 456);
INSERT INTO key_value VALUES ('KEY1', 'VALUE5', 3, 456);
INSERT INTO key_value VALUES ('KEY1', 'VALUE6', 2, 456);
INSERT INTO key_value VALUES ('KEY2', 'VALUE7', 1, 678);
INSERT INTO key_value VALUES ('KEY2', 'VALUE8', 3, 678);
INSERT INTO key_value VALUES ('KEY2', 'VALUE9', 2, 678);
SELECT key, regn_no, option1, option2, option3
FROM (
SELECT
key,
regn_no,
sortorder,
value AS option1,
LEAD(value, 1) OVER (PARTITION BY key, regn_no ORDER BY sortorder) AS option2,
LEAD(value, 2) OVER (PARTITION BY key, regn_no ORDER BY sortorder) AS option3
FROM key_value
) kv
WHERE
sortorder = (SELECT MIN(sortorder) FROM key_value WHERE key = kv.key AND regn_no = kv.regn_no)
;
Output:
KEY REGN_NO OPTION1 OPTION2 OPTION3
------ ---------- ----------- ------------ -------------
KEY1 123 VALUE1 VALUE3
KEY1 456 VALUE4 VALUE6 VALUE5
KEY2 123 VALUE2
KEY2 678 VALUE7 VALUE9 VALUE8
Ry this solution)
SELECT REGNO, KEY, MAX(CASE WHEN SortOrder = 1 THEN VALUE ELSE '' END) AS OPTION1,
MAX(CASE WHEN SortOrder = 2 THEN VALUE ELSE '' END) AS OPTION2,
MAX(CASE WHEN SortOrder = 3 THEN VALUE ELSE '' END) AS OPTION3
FROM SomeTable
GROUP BY REGNO, KEY
SELECT REGNO, KEY, MAX(CASE WHEN num= 1 THEN VALUE ELSE '' END) AS OPTION1,
MAX(CASE WHEN num= 2 THEN VALUE ELSE '' END) AS OPTION2,
MAX(CASE WHEN num= 3 THEN VALUE ELSE '' END) AS OPTION3
FROM
(
SELECT ROW_NUMBER() OVER(PARTITION BY REGNO, KEY ORDER BY SortOrder) AS num, * FROM SomeTable
) T GROUP BY REGNO, KEY

SQL - Sort Select from table

I have the following row from a table in MSSQL
Person | value1 | value2 | value3 | value4
John | 4 | 7 | 1 | 2
I want this row sorted according to the values as shown below.
Person | value2 | value1 | value4 | value3
John | 7 | 4 | 2 | 1
May be I'm asking a stupid question , I want the column names to be sorted according to the values in those column.
I know that this can be achieved using query
SELECT *
FROM tableName
ORDER BY value2, value1, value4, value3 DESC
But when I change the any column value, I have to change the query to get the result sorted.
Please help...
-- sample data
declare #t table
(
person varchar(50),
value1 int,
value2 int,
value3 int,
value4 int
)
insert into #t select 'John', 4, 7, 1, 2
insert into #t select 'Name1', 14, 7, 1, 16
insert into #t select 'Name2', 24, 8, 1, 2
-- query
select
person, v1 = [1], v2 = [2], v3 = [3], v4 = [4]
from
(
select person, rn = row_number() over(partition by person order by a desc), a
from #t t1
unpivot
(
a for b in (value1, value2, value3, value4)
) t2
) t1
pivot
(
max(a) for rn in ([1], [2], [3], [4])
) t2
unless I'm missing something, you should just append 'order by person, value2, value1, value4, value3' at the end of your select statement.
I think you want:
SELECT Person, Value2, Value1, Value4, Valuer
FROM YourTable
try this:
SELECT * FROM tableName ORDER BY value2, value1, value4, value3 DESC