Update Table column with values for other column - sql

I have a table along these lines:
Client | Date | Value 1 | Value 2 |
1 2013-11-08 159 159
1 2013-11-09 254 254
1 2013-12-05 512 512
1 2014-01-02 1200 1200
2 2013-11-10 189 189
2 2013-11-15 289 289
2 2013-12-22 585 585
2 2014-01-06 1650 1650
I need to update the table in SQL to look like this:
Client | Date | Value 1 | Value 2 |
1 2013-11-08 159 1200
1 2013-11-09 254 1200
1 2013-12-05 512 1200
1 2014-01-02 1200 1200
2 2013-11-10 189 1650
2 2013-11-15 289 1650
2 2013-12-22 585 1650
2 2014-01-06 1650 1650
The idea is that for each Client, Value 2 will become Value 1 where Date is most recent.

In SQL Server the best best thing to use is CTE with UPDATE statement. The query below demonstrates the syntax for what you need to do. All you have to do is substitute your table name and columns names.
;WITH MyUpdate
AS ( SELECT ClientId
,Value1
,ROW_NUMBER() OVER ( PARTITION BY ClientId ORDER BY MyDate DESC ) AS RowNum
FROM MyTable)
UPDATE MyTable
SET MyTable.Value2 = MyUpdate.Value1
FROM MyTable
INNER JOIN MyUpdate
ON MyUpdate.ClientID = MyTable.ClientID
AND RowNum = 1

Try this:
UPDATE TABLE1 T2 SET Value2 =
(SELECT T1.Value2 FROM TABLE1 T1 WHERE T1.Client = T2.Client AND
T1.Date = (SELECT MAX(T3.Date) FROM TABLE1 T3
WHERE T2.Client = T3.Client GROUP BY Client));
ORACLE

Related

Joins and/or Sub queries or Ranking functions

I have a table as follows:
Order_ID
Ship_num
Item_code
Qty_to_pick
Qty_picked
Pick_date
1111
1
1
3000
0
Null
1111
1
2
2995
1965
2021-05-12
1111
2
1
3000
3000
2021-06-24
1111
2
2
1030
0
Null
1111
3
2
1030
1030
2021-08-23
2222
1
3
270
62
2021-03-18
2222
1
4
432
0
Null
2222
2
3
208
0
Null
2222
2
4
432
200
2021-05-21
2222
3
3
208
208
2021-08-23
2222
3
4
232
200
2021-08-25
From this table,
I only want to show the rows that has the latest ship_num information, not the latest pick_date information (I was directed to a question like this that needed to return the rows with the latest entry time, I am not looking for that) for an order i.e., I want it as follows
Order_ID
Ship_num
Item_code
Qty_to_pick
Qty_picked
Pick_date
1111
3
2
1030
1030
2021-08-23
2222
3
3
208
208
2021-08-23
2222
3
4
232
200
2021-08-25
I tried the following query,
select order_id, max(ship_num), item_code, qty_to_pick, qty_picked, pick_date
from table1
group by order_id, item_code, qty_to_pick, qty_picked, pick_date
Any help would be appreciated.
Thanks in advance.
Using max(ship_num) is a good idea, but you should use the analytic version (with an OVER clause).
select *
from
(
select t.*, max(ship_num) over (partition by order_id) as orders_max_ship_num
from table1 t1
) with_max
where ship_num = orders_max_ship_num
order by order_id, item_code;
You can get this using the DENSE_RANK().
Query
;with cte as (
select rnk = dense_rank()
over (Partition by order_id order by ship_num desc)
, *
from table_name
)
Select *
from cte
Where rnk =1;

Query for replacing data if the value is not number

I have a similar problem like this thread but is bit different what it required
https://community.oracle.com/thread/4132183
I have the following table:
Table1:
ID empID employeeactive dtefrom dateto mgrid
1 123 1 1/10/2016 113
2 213 0 1/20/2015 1/20/2016 323
3 213 1 1/20/2016 423
4 312 0 1/05/2016 1/30/2017 523
5 512 1 1/30/2017 623
6 812 1 2/30/2017 6543
Table2:
empID emplyactive supid
123 1 -
213 1 -
312 1 -
512 0 -
612 1 -
712 1 -
812 1 872
912 0 222
I have this table instead of - i want to replace with mgrid in table 1.. and table2 have extra data which is not in table1 so i have to ignore the extra data if supid '-' and also want to have emplyactive =1 but some of the emplyactive=1 table 1 has multiple mgr id ...
so I tried this one
select empid , decode(supid,'-',mgrid,supid) from table2,table1 where
empid(+) = empid and emplyactive =1 and employeeactive=1
so I am getthing how to solve this please help me out thank you .. if some thing like and exists will work thanks in advance.
This is what I am trying to insert in a package body oracle.
This is how the output looks like:
empID emplyactive supid
123 1 113
213 1 423
812 1 872
select a.empid, a.emplyactive, max(a.supid) supid
from (
select * from #table2
union
select empid, employeeactive, mgrid from #table1)a
left join #table1 b on a.empid=b.empid and employeeactive=1
join #table2 c on a.empid=c.empid and c.emplyactive=1
where a.emplyactive=1
and a.supid<>0
group by a.empid, a.emplyactive

SQL sum by month with the previous values

I have following data:
cohort activity counter
-----------------------------
2010-12 0 470
2010-12 1 2
2010-12 2 1
2010-12 3 1
2010-12 6 1
2011-01 0 550
2011-01 1 1
2011-01 6 1
I want to sum counter of different activities by month, so the final table looks like:
cohort activity counter sumResult
-------------------------------------------
2010-12 0 470 470
2010-12 1 2 472
2010-12 2 1 473
2010-12 3 1 474
2010-12 6 1 475
2011-01 0 550 550
2011-01 1 1 551
2011-01 6 1 552
I've tried to do it like this:
select
a.activity, a.counter, a.cohort,
(
select sum(b.counter)
from data_table as b
where b.cohort = a.cohort and b.counter >= a.counter
) as sumResult
from data_table as a;
GO;
but it gave me strange results as:
cohort activity counter sumResult
-------------------------------------------
2010-12 0 470 470
2010-12 1 2 472
2010-12 2 1 475
2010-12 3 1 475
2010-12 6 1 475
2011-01 0 550 550
2011-01 1 1 552
2011-01 6 1 552
What could be a problem?
Depends on your RDBMS , some(SQL Server,Oracle,Postgresql) of them will accept SUM() OVER() :
SELECT t.*,
SUM(t.counter) OVER(PARTITION BY t.cohort ORDER BY t.activity) as sumResult
FROM YourTable t
If it's another, that's a bit more complicated and can be dealt with JOINS
The normal way to do this uses the ANSI standard cumulative sum function:
select dt.*,
sum(dt.counter) over (partition by dt.cohort order by dt.counter desc)
from data_table dt
order by cohort, counter desc;
If you want to use a subquery, the you need a stable sort, and activity can give you one. You can use this in the cumulative sum syntax:
select dt.*,
sum(dt.counter) over (partition by dt.cohort order by dt.counter desc, dt.activity)
from data_table dt
order by cohort, counter desc, activity;
Or using a subquery:
select dt.*,
(select sum(dt2.counter)
from data_table dt2
where dt2.cohort = dt.cohort and
(dt2.counter > dt.counter or
dt2.counter = dt.counter and dt2.activity < dt.activity)
)
from data_table dt
order by cohort, counter desc, activity;

SQL transpose data

I need to transpose data that looks like the following. I don't need to use any aggregate functions, just want to transpose columns to rows.
Current view:
Name | Code1 | Code2 | Code3 | Pct1 | Pct2 | Pct3 | Amt1 | Amt2 | Amt3
Name1 123 124 125 50 25 25 1000 1500 1555
Name2 123 124 125 50 25 25 1222 1520 1600
What I Need:
AccountName | Code# | Pct | Amt
Name1 123 50 1000
Name1 124 25 1500
Name1 125 25 1555
Name2 123 50 1222
Name2 124 25 1520
Name2 125 25 1600
if this is possible, could you also include where I would place my joins if I need to use data in a different table?
I'm using SQL Server Management Studio 2014 and I don't have the permission to create tables
This is a neat trick using table valued expression
SELECT [Name], ca.*
From myTable
CROSS APPLY (Values
(Code1, Pct1, Amt1),
(Code2, Pct2, Amt2),
(Code3, Pct3, Amt3)
) ca([Code#], [Pct], [Amt])
select
Name,
case n when 1 then Code1 when 2 then Code2 when 3 then Code3 end as Code,
case n when 1 then Pct1 when 2 then Pct2 when 3 then Pct3 end as Pct,
case n when 1 then Amt1 when 2 then Amt2 when 3 then Amt3 end as Amt
from T cross join (values (1), (2), (3)) multiplier(n)
The basic idea is to triplicate the rows and then use case to pick out the correct values.

List the last two records for each id

Good Afternoon!
I'm having trouble list the last two records each idmicro
Ex:
idhist idmicro idother room unit Dtmov
100 1102 0 8 coa 2009-10-23 10:40:00.000
101 1102 0 1 coa 2009-10-28 10:40:00.000
102 1102 0 2 dib 2008-10-24 10:40:00.000
103 1201 0 6 diraf 2008-10-23 10:40:00.000
104 1201 0 7 diraf 2009-10-21 10:40:00.000
105 1201 0 4 dimel 2008-10-22 10:40:00.000
Would look like this:
ex:
result
idhist idmicro idoutros room unit Dtmov
101 1102 0 1 coa 2009-10-28 10:40:00.000
102 1102 0 2 dib 2008-10-24 10:40:00.000
103 1201 0 6 diraf 2008-10-22 10:40:00.000
104 1201 0 7 diraf 2009-10-21 10:40:00.000
I'm starting to delve into SQL and am having trouble finding this solution
Sorry
Thank you.
EDIT: I am using SQL server, and I made no query.
Yes! is based on the date and time
You can do the same thing with an imbricated SELECT statement.
SELECT *
FROM (
SELECT row_number() OVER (
PARTITION BY idmicro ORDER BY idhist
) AS ind
,*
FROM data
) AS initialResultSet
WHERE initialResultSet.ind < 3
Here is a sample SQLFiddle with how this query works.
WITH etc
AS (
SELECT *
,row_number() OVER (
PARTITION BY idmicro ORDER BY idhist
) AS r
,count() OVER (
PARTITION BY idmicro ORDER BY idhist
) cfrom TABLE
)
SELECT *
FROM etc
WHERE r > c - 2
Use row_number and over partition
SELECT *
FROM (
SELECT *, row_number() OVER (PARTITION BY idmicro ORDER BY idhist desc) AS rownum
FROM data
) AS initialResultSet
WHERE initialResultSet.rownum<=2