Update entry(ies) in Oracle table using temporary column - sql

How can I update the a.age and b.age to 32 for all the results obtained by the below query.the temp column is "CID" as shown in below example
select *
from (SELECT ROW_NUMBER()
OVER (PARTITION BY CUST_NAME ORDER BY CUST_NAME) AS CID,CUST_NAME,AGE,CITY,COLUMNB
FROM (select CUST_NAME,AGE,CITY,COLUMNB
from SOMETABLE
where date = '26-jULY-2012'))a
RIGHT join (select *
from (SELECT ROW_NUMBER()
OVER (PARTITION BY CUST_NAME ORDER BY CUST_NAME) AS CID,CUST_NAME,AGE,CITY,COLUMNB
FROM (select CUST_NAME,AGE,CITY,COLUMNB
from SOMETABLE2
where date = '26-jULY-2012')))b
on a.CID=b.CID
and a.CUST_NAME=b.CUST_NAME
ORDER BY a.CUST_NAME,A.CID,a.COLUMNB;

update sometable
set age = 32
where cid in (
select a.cid
from (SELECT ROW_NUMBER()
OVER (PARTITION BY CUST_NAME ORDER BY CUST_NAME) AS CID,CUST_NAME,AGE,CITY,COLUMNB
FROM (select CUST_NAME,AGE,CITY,COLUMNB
from SOMETABLE
where date = '26-jULY-2012'))a
RIGHT join (select *
from (SELECT ROW_NUMBER()
OVER (PARTITION BY CUST_NAME ORDER BY CUST_NAME) AS CID,CUST_NAME,AGE,CITY,COLUMNB
FROM (select CUST_NAME,AGE,CITY,COLUMNB
from SOMETABLE2
where date = '26-jULY-2012')))b
on a.CID=b.CID
and a.CUST_NAME=b.CUST_NAME
)
;
update sometable2
set age = 32
where cid in (
select b.cid
from (SELECT ROW_NUMBER()
OVER (PARTITION BY CUST_NAME ORDER BY CUST_NAME) AS CID,CUST_NAME,AGE,CITY,COLUMNB
FROM (select CUST_NAME,AGE,CITY,COLUMNB
from SOMETABLE
where date = '26-jULY-2012'))a
RIGHT join (select *
from (SELECT ROW_NUMBER()
OVER (PARTITION BY CUST_NAME ORDER BY CUST_NAME) AS CID,CUST_NAME,AGE,CITY,COLUMNB
FROM (select CUST_NAME,AGE,CITY,COLUMNB
from SOMETABLE2
where date = '26-jULY-2012')))b
on a.CID=b.CID
and a.CUST_NAME=b.CUST_NAME
)
;

Related

Results of a CTE inside a subquery and row_number with a couple order by

I have a query that runs as follows:
WITH teste1 as (
SELECT
CONCAT(a.pid, a.num_ordenado) as id_despacho,
a.pid,
a.created_at,
a.nota,
a.from_id,
a.from_nome
FROM (
SELECT pid, id,
(ROW_NUMBER() over (partition by pid order by created_at)) as num_ordenado,
from_id, from_nome, nota, created_at
FROM mytable_a) as a
),
teste2 as (
SELECT
CONCAT(t.pid, t.ordenado) as id_despacho,
t.ordenado,
t.pid as id_doc,
t.data as diahora,
CONCAT
(
'Evento: ', t.evento
) as conteudo2,
'' as pasta,
t.from_id,
t.from_nome,
t.to_id,
t.to_nome
FROM
(
SELECT pid, data,
(ROW_NUMBER() over (partition by pid order by data)) as ordenado,
from_id, from_nome, to_id, to_nome, evento
FROM mytable_t) as t
)
SELECT *
FROM teste2 as t2
LEFT JOIN teste1 as t1
ON t2.id_despacho = t1.id_despacho
WHERE t2.conteudo2 <> 'Evento: Campo bloqueado' AND t2.conteudo2 <> 'Evento: Campo desbloqueado'
In each CTE, I order the ID's by datetime and then create a new ID structure on which I join by that new ID at the last query. I'm wondering how could I do to now order them again by datetime.
My questions then would be:
Can I use the results of a CTE (teste1 and teste2 tables) inside a subquery? Something like this (not working)
SELECT
t2.id_despacho,
t2.id_doc,
t2.diahora,
t2.conteudo2,
t1.id_despacho,
t1.created_at,
t1.nota,
(ROW_NUMBER() OVER (PARTITION BY id_doc ORDER BY diahora, created_at)) AS ordenado_final
FROM
(SELECT *
FROM teste2 AS t2
LEFT JOIN teste1 AS t1 ON t2.id_despacho = t1.id_despacho
WHERE t2.conteudo2 <> 'Evento: Campo bloqueado'
AND t2.conteudo2 <> 'Evento: Campo desbloqueado')
Does that ROW_NUMBER() work like that? Can I order by two different columns?
(ROW_NUMBER() OVER (PARTITION BY id_doc
ORDER BY diahora, created_at)) AS ordenado_final

Is this query valid for calculating the max gap between active dates for each user?

I have the following task:
Write a query to get the max gap between active dates for each user in the following table:
(e.g, user 1 will have max. gap of 3 days, user 2 will have 30 days, and user 3 will have null.)
CREATE TABLE IF NOT EXISTS `gamers` (
`id` int(6) not null,
`user_id` int(3) not null,
`active_date` DATE Not null,
PRIMARY KEY (`id`)
);
INSERT INTO `gamers` (`id`,`user_id`,`active_date`) VALUES
('1','1','2019-01-01'),
('2','1','2019-01-02'),
('3','1','2019-01-05'),
('4','2','2019-03-01'),
('5','2','2019-03-31'),
('6','3','2019-04-01');
My solution would be the following:
SELECT g.id as id, g.user_id, MAX(total_amount_spent) OVER(PARTITION BY g.country), g.country
FROM gamers2 as g
INNER JOIN cte as c
ON c.country = g.country
WHERE install_source = 'ua' AND g.id NOT IN (SELECT id FROM cte)
GROUP BY g.country
ORDER BY g.user_id, total_amount_spent DESC
),
cte3 AS(
SELECT g.id, g.user_id, MAX(total_amount_spent) OVER(PARTITION BY g.country), g.country
FROM gamers2 as g
INNER JOIN cte2 as c
ON c.country = g.country
WHERE install_source = 'ua' AND g.id NOT IN (SELECT id FROM cte2)
GROUP BY g.country
ORDER BY g.user_id, total_amount_spent DESC
)
SELECT * FROM cte
UNION
SELECT * FROM cte2
UNION
SELECT * FROM cte3
We can use LAG() combined with ROW_NUMBER() as follows:
WITH cte AS (
SELECT *, LAG(active_date, 1, active_date) OVER
(PARTITION BY user_id ORDER BY active_date) lag_active_date
FROM gamers2
),
cte2 AS (
SELECT *, DATEDIFF(active_date, lag_active_date) AS diff,
ROW_NUMBER() OVER (PARTITION BY user_id
ORDER BY DATEDIFF(active_date, lag_active_date) DESC) AS rn
FROM cte
)
SELECT user_id, diff
FROM cte2
WHERE rn = 1;
A bit more readable, in my opinion:
WITH
w_lag_val AS (
SELECT
id
, user_id
, active_date
, active_date
- LAG(active_date) OVER(
PARTITION BY user_id ORDER BY active_date
)
AS lag_val
FROM gamers
)
SELECT
user_id
, MAX(lag_val) AS max_gap
FROM w_lag_val
GROUP BY user_id
ORDER BY user_id
;
-- out user_id | max_gap
-- out ---------+---------
-- out 1 | 3
-- out 2 | 30
-- out 3 | (null)
select *, max(diff) from (
select *, DATEDIFF( f,active_date)as diff from (
SELECT gamers.id , gamers.user_id, gamers.active_date,
(select active_date from gamers as g1 where g1.active_date > gamers.active_date and gamers.user_id = g1.user_id order by g1.active_date limit 1) as f
from gamers
order by gamers.id) as vv) as gg
group by user_id
there is another solution

Random allocation of records between two tables

I want to assign the values from Table B to Table A, but so that each record in Table B occurs in the same number of repetitions.
Fiddle SQL
You can use window functions for this and mod arithmetic. For simple repetition:
with a as (
select a.*, rownum as seqnum
from a
),
b as (
select b.*, rownum as seqnum, count(*) over () as cnt
from b
)
select a.col, b.col
from a join
b
on mod(a.seqnum - 1, b.cnt) = b.seqnum - 1;
For more random assignment, randomize the seqnums:
with a as (
select a.*,
row_number() over (order by dbms_random.random) as seqnum
from a
order by db
),
b as (
select b.*, count(*) over () as cnt,
row_number() over (order by dbms_random.random) as seqnum
from b
)
select a.col, b.col
from a join
b
on mod(a.seqnum - 1, b.cnt) = b.seqnum - 1;
You can use the ROWNUM for achieving the same:
SELECT
COLOUR,
EMP
FROM
(
SELECT
COLOUR,
ROWNUM RN
FROM
T1
) T1,
(
SELECT
EMP,
ROWNUM RN
FROM
T2
) T2
WHERE
MOD(T1.RN, 2) + 1 = T2.RN
Fiddler SQL QUERY
Try this,
with Employees as
(select Emp, Row_Number() Over(order by 1) Rn
from B
cross join (select 1
from Dual
connect by level < (select count(1)
from A) / (select count(1)
from B) + 1)
order by Dbms_Random.Value),
Colours as
(select Colour, Rownum Rn
from A)
select t.Colour, k.Emp
from Colours t
join Employees k
on t.Rn = k.Rn

How to ignore column in SQL Server

I have this query:
Select *
from
(Select
*
ROW_NUMBER() OVER (PARTITION BY TID ORDER BY TID) AS RowNumber
from
MyTable
where
Eid = 'C1') as a
where
a.RowNumber = 1
and it displays these results:
Column1 Column2 RowNumber
------------------------------
Value1 value2 1
I want to ignore the RowNumber column in the select statement and I don't want to list all columns in select query (100+ columns and given is just an example).
How to do this in SQL Server?
Well, you would have to list all the columns in the outer select, if you use a subquery and row_number() to get a unique row.
An alternative method uses a correlated subquery, but requires having some unique column in the table. If you have one:
select t.*
from mytable t
where t.col = (select max(t2.col) from mytable t2 where t2.tid = t.tid and t2.eid = 'C1');
With the right indexes, this can have better performance than the row_number() version.
If you don't have a unique column, you can do:
select t.*
from (select distinct tid from mytable where eid = 'C1') tc cross apply
(select top 1 t.*
from mytable t
where t.tid = tc.tid and t.eid = 'C1'
) t;
Wrap your query as a subquery and select specific columns from it like so:
SELECT x.Column1, x.Column2
FROM
(
Select * from (Select * ROW_NUMBER() OVER (PARTITION BY TID ORDER BY TID)
AS RowNumber from MyTable where Eid="C1") as a where a.RowNumber=1
) AS x
OR Change your original Select to:
Select a.[Column1], a.[Column2]
from
(
Select * ROW_NUMBER() OVER (PARTITION BY TID ORDER BY TID)
AS RowNumber from MyTable where Eid="C1"
) as a
Where a.RowNumber=1
Replace * from your query in clarify exactly columnd which you whant
select x.Column1, x.Column2 FROM (
Select * from (Select * ROW_NUMBER() OVER (PARTITION BY TID ORDER BY TID)
AS RowNumber from MyTable where Eid="C1") as a where a.RowNumber=1) AS x

expecting output with out using left join

first table is my input and expecting output like second table with out using left join.
this is the table data
declare #table table
(customer_id int,
indicator bit,
salary numeric(22,6)
,netresult numeric(22,6))
INSERT INTO #table (
customer_id
,indicator
,salary
)
VALUES
(1,1,2000),
(1,1,3000),
(2,1,1000),
(1,0,500),
(1,1,5000),
(2,1,2000),
(2,0,100)
select * from #table order by customer_id,indicator desc
I tried in below method it works. Is there any better alternative?
SELECT a.customer_id
,a.indicator
,a.salary
,netresult=p_salary-(2*n_salary)
FROM (
SELECT customer_id
,indicator
,salary
,sum(salary) OVER (PARTITION BY customer_id) p_salary
FROM #table
) a
LEFT JOIN (
SELECT customer_id
,indicator
,salary
,sum(salary) OVER (PARTITION BY customer_id) n_salary
FROM #table
WHERE indicator = 0
) b ON a.customer_id = b.customer_id
order by customer_id,indicator desc
Expected Output
I think you want this:
select t.customer_id, t.indicator,
sum(case when indicator = 1 then salary else - salary end) over (partition by customer_id) as netresult
form #table t;
No joins are necessary.
with math
select t.customer_id, t.indicator, t.salary
, sum((( t.indicator * 2) -1) * salary) over (partition by customer_id) as netresult
from #table t;