Select SQL Columns as added rows - sql

I have a SQL Server 2008 table as below...
ID Others1Desc Others1Value Others2Desc Others2value
-- ----------- ------------ ----------- ------------
id_x xyz 12.50 pqr 10.00
id_y abc NULL mno 1.05
Now, I want the select result as below...
ID ItemDesc ItemValue
-- ----------- ------------
id_x xyz 12.50
id_x pqr 10.00
id_y abc NULL
id_y mno 1.05
Any guidance is highly appreciated. Thanks

And another way is using cross apply and values clause like this
DECLARE #temp table (ID [varchar](100), Others1Desc [varchar](100), Others1Value decimal(11, 2), Others2Desc [varchar](100), Others2Value decimal(11, 2));
INSERT #temp (ID, Others1Desc, Others1Value, Others2Desc, Others2Value) VALUES ('id_x', 'xyz', 12.50, 'pqr', 10.00);
INSERT #temp (ID, Others1Desc, Others1Value, Others2Desc, Others2Value) VALUES ('id_y', 'abc', NULL, 'mno', 1.05);
select ID, t.* from #temp
cross apply
(
values (Others1Desc, Others1Value),
(Others2Desc, Others2Value)
) t(ItemDesc, ItemValue)
Result
ID ItemDesc ItemValue
--------------------------
id_x xyz 12.50
id_x pqr 10.00
id_y abc NULL
id_y mno 1.05

You can use UNION ALL to do this:
select ID, Others1Desc as ItemDesc, Others1Value as ItemValue
from yourtable
union all
select ID, Others2Desc as ItemDesc, Others2Value as ItemValue
from yourtable

This way:
select ID, Others1Desc as ItemDesc,Others1Value as itemValue from
(select ID , Others1Desc , Others1Value from table1
Union all
select ID , Others2Desc, Others2value from table1)as a

Related

How to JOIN two rows into one row SQL

Table 1:
ID
Name
Class
Date
Intime
Outtime
INAM
OUTPM
1
Smith
1st
07-12-2022
8:30 AM
Null
P
Null
1
Smith
1st
07-12-2022
Null
4:30 PM
Null
P
How to join these two rows into a single row?
Required output:
ID
Name
Class
Date
Intime
Outtime
INAM
OUTPM
1
Smith
1st
07-12-2022
8:30 AM
4:30 PM
P
P
Can someone please help me to join into a single row? Thank you...
You may aggregate by the first 4 columns and take the max of the final 4 columns:
SELECT ID, Name, Class, Date,
MAX(Intime) AS Intime, MAX(Outtime) AS Outtime, MAX(INAM) AS INAM,
MAX(OUTPM) AS OUTPM
FROM yourTable
GROUP BY ID, Name, Class, Date;
SELECT
FK,
MAX(Field1) AS Field1,
MAX(Field2) AS Field2
FROM
table1
GROUP BY
FK;
I used MAX, but any aggregate which picks one value from among the GROUP BY rows should work.
Test data:
CREATE TABLE table1 (FK int, Field1 varchar(10), Field2 varchar(10));
INSERT INTO table1 VALUES (3, 'ABC', NULL);
INSERT INTO table1 VALUES (3, NULL, 'DEF');
INSERT INTO table1 VALUES (4, 'GHI', NULL);
INSERT INTO table1 VALUES (4, 'JKL', 'MNO');
INSERT INTO table1 VALUES (4, NULL, 'PQR');
Results:
FK Field1 Field2
-- ------ ------
3 ABC DEF
4 JKL PQR

Find sum() from two different tables and join them based on a condition?

I have two tables,
Table1:
ID Amount Date
------------------
123 500.00 02-Sep-2020
123 240.00 02-Sep-2020
124 200.50 02-Sep-2020
125 150.70 03-Sep-2020
123 480.80 03-Sep-2020
Table2
ID Settled_Amount Date
-------------------------------
123 150.25 02-Sep-2020
124 200.00 03-Sep-2020
125 100.40 03-Sep-2020
I want to sum the Amount column of table1 and sum the settled_amount column of Table2 of a particular ID group by the Date column.
So My result would be for ID=123:
Sum(Amount) Sum(Settled_amount) Date
------------------------------------------
740.00 150.25 02-Sep-2020
480.80 03-Sep-2020
You can use union all and group by. For all ids:
select id, date, sum(amount), sum(amount_settled)
from ((select id, date, amount, null as amount_settled
from table1
) union all
(select id, date, null as amount, amount_settled
from table2
)
) t
group by id, date
order by date;
You can filter for a particular id using a where clause in the outer query.
Another way to write it without subseleting as Gordon does.
declare #table1 table (id int, amount numeric(18,2), Dates Date)
Insert into #table1
values
(123 ,500.00 ,'02-Sep-2020'),
(123 ,240.00 ,'02-Sep-2020'),
(124 ,200.50 ,'02-Sep-2020'),
(125 ,150.70 ,'03-Sep-2020'),
(123 ,480.80 ,'03-Sep-2020')
declare #table2 table (id int, Settled_Amount numeric(18,2), Dates Date)
insert into #table2
values
(123 , 150.25 ,'02-Sep-2020'),
(124 , 200.00 ,'03-Sep-2020'),
(125 , 100.40 ,'03-Sep-2020');
with Table1 as (
select sum(amount) as Amount,ID,Dates from #table1
group by ID,Dates
)
,
Table2 as (
Select sum(Settled_amount) as Settled_amount, ID,Dates from #table2
group by ID,Dates
)
select Amount,Settled_amount,a.Dates,a.ID from Table1 a left join table2 b on a.id = b.id and a.Dates = b.Dates
where a.id=123

Transform rows to columns(probably pivot)

Here is my requirement:
create table #TEMP
(
KEY_VALUE VARCHAR(100)
,NAME VARCHAR(100)
,AMOUNT INT
,QUANTITY INT
)
INSERT INTO #TEMP
VALUES
('K1','ABC',100,10000),
('K2','XYZ',200,20000),
('K1','ABC',50,5000),
('K2','XYZ',300,30000),
('K3','MNO',50,500)
select * from #TEMP
Because the KEY_VALUE COLUMN matches for 2 rows(K1 and K2), I want to transform it to something as below:
KEY_VALUE NAME AMOUNT_1 AMOUNT_2 QUANTITY_1 QUANTITY_2
K1 ABC 100 50 10000 5000
K2 XYZ 200 300 20000 30000
K3 MNO 50 NULL 500 NULL
What/How do I do that? Please let me know if my question is not clear.
You can use ROW_NUMBER() & do conditional aggregation :
SELECT KEY_VALUE, NAME,
MAX(CASE WHEN seq = 1 THEN AMOUNT END) AS AMOUNT_1,
MAX(CASE WHEN seq = 2 THEN AMOUNT END) AS AMOUNT_2,
MAX(CASE WHEN seq = 1 THEN QUANTITY END) AS QUANTITY_1,
MAX(CASE WHEN seq = 2 THEN QUANTITY END) AS QUANTITY_2
FROM (SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY KEY_VALUE ORDER BY AMOUNT) AS seq
FROM #TEMP t
) t
GROUP BY KEY_VALUE, NAME;
EDIT : If you want to do further calculation then you can use CTE :
WITH CTE AS (
<query>
)
SELECT C.*,
C.AMOUNT_1 - C.AMOUNT_1 AS Diff_Amt
FROM CTE C;
Prepare data
CREATE TABLE #t (
key_value varchar(10),
name varchar(10),
amount int,
quantity int
);
INSERT INTO #t
VALUES
('K1', 'ABC', 100, 10000),
('K2', 'XYZ', 200, 20000),
('K1', 'ABC', 50, 5000),
('K2', 'XYZ', 300, 30000),
('K3', 'MNO', 50, 500);
Querying
WITH t1 (id, key_value, name, amount, quantity)
AS (
SELECT ROW_NUMBER() OVER (ORDER BY key_value), key_value, name, amount, quantity FROM #t
),
t2
AS (
SELECT MIN(id) AS min_id, MAX(id) AS max_id, key_value, name
FROM t1
GROUP BY key_value, name
),
t3
AS (
SELECT t2.key_value, t2.name,
t11.amount AS amount_1, t11.quantity AS quantity_1,
t12.amount AS amount_2, t12.quantity AS quantity_2
FROM t2
INNER JOIN
t1 t11 ON t11.key_value = t2.key_value AND t11.name = t2.name
AND t11.id = t2.min_id
LEFT JOIN
t1 t12 ON t12.key_value = t2.key_value AND t12.name = t2.name
AND t12.id = t2.max_id AND t12.id <> t2.min_id
)
SELECT * FROM t3
Result
key_value name amount_1 quantity_1 amount_2 quantity_2
---------- ---------- ----------- ----------- ----------- -----------
K1 ABC 100 10000 50 5000
K2 XYZ 300 30000 200 20000
K3 MNO 50 500 NULL NULL

How to get rows from two tables on maximum value of particular field

I have two tables that has date_updated column.
TableA is like below
con_id date_updated type
--------------------------------------------
123 19/06/2018 2
123 15/06/2018 1
123 01/05/2018 3
101 06/04/2018 1
101 05/03/2018 2
And I have TableB that also has the same structure
con_id date_updated type
--------------------------------------------
123 15/05/2018 2
123 01/05/2018 1
101 07/06/2018 1
The resultant table should have the data with the recent date
con_id date_updated type
--------------------------------------------
123 19/06/2018 2
101 07/06/2018 1
Here the date_updated column is datetime datatype of sql server. I tried this by using group by and selecting the maximum date_updated. But i am not able to include column type in select statement. When i used type in group by ,the result is not correct as the type is also grouped. How can i query this. Please help
SELECT *
FROM
(SELECT *, ROW_NUMBER() OVER(Partition By con_id ORDER BY date_updated DESC) as seq
FROM
(SELECT * FROM TableA
UNION ALL
SELECT * FROM TableB) as tblMain) as tbl2
WHERE seq = 1
One method:
WITH A AS(
SELECT TOP 1 con_id,
date_updated,
type
FROM TableA
ORDER BY date_updated DESC),
B AS(
SELECT TOP 1 con_id,
date_updated,
type
FROM TableB
ORDER BY date_updated DESC),
U AS(
SELECT *
FROM A
UNION ALL
SELECT *
FROM B)
SELECT *
FROM U;
The 2 CTE's at the top get your most recent rows from the tables, and then the end statement unions them together.
For the benefit of the person who says this doesn't work:
USE Sandbox;
GO
CREATE TABLE tablea (con_id int, date_updated date, [type] tinyint);
CREATE TABLE tableb (con_id int, date_updated date, [type] tinyint);
GO
INSERT INTO tablea
VALUES
(123,'19/06/2018',2),
(123,'15/06/2018',1),
(123,'01/05/2018',3),
(101,'06/04/2018',1),
(101,'05/03/2018',2);
INSERT INTO tableb
VALUES
(123,'15/05/2018',2),
(123,'01/05/2018',1),
(101,'07/06/2018',1);
GO
WITH A AS(
SELECT TOP 1 con_id,
date_updated,
[type]
FROM TableA
ORDER BY date_updated DESC),
B AS(
SELECT TOP 1 con_id,
date_updated,
[type]
FROM TableB
ORDER BY date_updated DESC),
U AS(
SELECT *
FROM A
UNION ALL
SELECT *
FROM B)
SELECT *
FROM U;
GO
DROP TABLE tablea;
DROP TABLE tableb;
This returns the dataset:
con_id date_updated type
----------- ------------ ----
123 2018-06-19 2
101 2018-06-07 1
Which is identical to the OP's data:
con_id date_updated type
--------------------------------------------
123 19/06/2018 2
101 07/06/2018 1
Hope this helps:
WITH combined
AS(
select * FROM tableA
UNION
select * FROM tableB)
SELECT t1.con_id,
t1.date_updated,
t1.type
FROM (
SELECT con_id,
date_updated,
type,
row_number() OVER(partition BY con_id ORDER BY date_updated DESC) AS rownumber
FROM combined) t1
WHERE rownumber = 1;
Can be done using window functions:
declare #TableA table (con_id int, date_updated date, [type] int)
declare #TableB table (con_id int, date_updated date, [type] int)
insert into #TableA values
(123, '2018-06-19', 2)
, (123, '2018-06-15', 1)
, (123, '2018-05-01', 3)
, (101, '2018-04-06', 1)
, (101, '2018-03-05', 2)
insert into #TableB values
(123, '2018-05-15', 2)
, (123, '2018-05-01', 1)
, (101, '2018-06-07', 1)
select distinct con_id
, first_value(date_updated) over (partition by con_id order by con_id, date_updated desc) as con_id
, first_value([type]) over (partition by con_id order by con_id, date_updated desc) as [type]
from
(Select * from #TableA UNION Select * from #TableB) x

SQL Server 2008 Select all columns of a table + a column from the same table based on a column value

I have a table VERSION with composite keys docId, verId:
docId verId apprvDt old_verId
------ ------ ----------- ----------
A 3 03/20/2017 2
A 2 03/18/2017 1
A 1 03/16/2017 null
B 1 03/18/2017 null
C 2 03/20/2017 1
C 1 03/16/2017 null
Say I select docId=A, verId=3, query should return
docId verId apprvDt old_verId old_apprvDt
------ ------ ----------- ---------- ------------
A 3 03/20/2017 2 03/18/2017
that is to retrieve the apprvDt of the old_verId.
I tried like this
select a.docId, a.verId, a.apprvDt, a.old_verId, b.old_apprvDt
from VERSION as a left join
(select x.docId, x.verId, x.apprvDt as old_apprvDt from REVISN as x
where x.docId = 'A' and x.verId = a.old_verId) as b
on b.docId = a.docId and b.verId = a.old_verId
but I am getting a multi-part binding error.
I want to select a row from VERSION including the apprvDt (old_apprvDt) of old_verId
Solution to your problem is as given below :
DECLARE #tbl TABLE(docId varchar(100), verId int, apprvDt datetime, old_verId int)
insert into #tbl values('A', 3 , '03/20/2017', 2)
insert into #tbl values('A', 2 , '03/18/2017', 1)
insert into #tbl values('A', 1 , '03/16/2017', NULL)
insert into #tbl values('B', 1 , '03/18/2017', NULL)
insert into #tbl values('C', 2 , '03/20/2017', 1)
insert into #tbl values('C', 1 , '03/16/2017', NULL)
select * from #tbl
;with data_table
as
(
select docId,verId,apprvDt,old_verId,
(select apprvDt from #tbl T2 where T2.docId=t1.docid and T2.verId=t1.old_verId)
old_apprvDt from #tbl t1
)
select * from data_table where docId='A' and verId=3
Result is as below :
-------------------------------------------------------------------------------------
docId verId apprvDt old_verId old_apprvDt
-------------------------------------------------------------------------------------
A 3 2017-03-20 00:00:00.000 2 2017-03-18 00:00:00.000
select t1.*,
b.apprvdt as old_apprvdt
from table1 t1
cross apply
(
select apprvdt from table1 t2 where t1.docid=t2.docid
and t2.old_verid =t1.verid ) b