Update value SQL table from another table - sql

I have this tables:
I need to update sum_ok and avg_ok considering values from table 1 like this:
I have this code SQL, but don't work fine:
update
t2
set sum_ok = sum(case when t2.[status]='OK' then 1 else 0 end )
,avg_ok = avg(case when t2[status]='OK' then status end )
from t1
inner join t2
on t1.A = t2.A --and t1.C = t2.C
where C is not null
group by A, C
Thanks!!

One option is to compute your "sum_ok" and "avg_ok" values separately, then apply the UPDATE statement while joining your "t2" table and your computed values:
WITH cte AS (
SELECT A,
C,
SUM(CASE WHEN [status] = 'ok' THEN 1 END) AS sum_ok,
AVG(CAST ([value] AS FLOAT)) AS avg_ok
FROM t1
GROUP BY A, C
)
UPDATE t2
SET t2.sum_ok = cte.sum_ok,
t2.avg_ok = cte.avg_ok
FROM t2
INNER JOIN cte
ON t2.A = cte.A AND t2.C = cte.C;
Check the demo here.
Note: in your query you're trying to access the "t2.status" field, whereas "t2" table doesn't have it.

Related

SQL join greater than / less then

I have 2 tables
I
So i need to get a table in which rows will be excluded for which the date for each "id" is more than in the second table "datestop"
I tried inner join with double condition:
id = id and Date < DateStop, but in this way also excluded rows which not contained in table 2 (id1)
For imagine, thats what i want to get:
I would use NOT EXISTS which is very efficient:
select t1.*
from table1 t1
where not exists (
select 1 from table2 t2
where t2.id = t1.id and t2.datestop <= t1.date
)
It's not clear if you need the value of Status must be 'Stopped' for your requirement.
So maybe you need to change the WHERE clause of the subquery to:
where t2.id = t1.id and t2.datestop <= t1.date and t2.status = 'Stopped'
Consider:
select a.*
from tablea a
left join tableb b on b.id = a.id
where b.id is null or b.datestop > a.date
This phrases as: get all records in tablea for which either there is no record with the same id in tableb, or whose date is less than the datestop of the corresponding record in tableb.
This is a situation where all can be helpful:
select a.*
from a
where a.date < all (select b.datestop
from b
where b.id = a.id and b.status = 'Stopped'
);

compare each row in first column with all rows in second column

I have a table with two columns. I want to compare each row of the first column with all rows in the second column. If matched I need to insert yes in the 3rd column, if not I need to insert no.
First second
A B
C D
E A
X c
Output should be
First second yesOrno
A B yes
C D yes
E A NO
X c NO
Use an EXISTS with the same table.
UPDATE T1 SET
ThirdColumn = CASE WHEN EXISTS (
SELECT
'a SecondColumn match exists'
FROM
YourTable AS T2
WHERE
T1.FirstColumn = T2.SecondColumn) THEN 'Yes' ELSE 'No' END
FROM
YourTable AS T1
SELECT
First, Second,
CASE WHEN EXISTS (
SELECT * FROM Table t2
WHERE t2.Second = t1.First)
THEN 'Yes' ELSE 'No' END AS YesOrNo
FROM
Table t1
you can get it by self join as below
select T1.First,T1.second,(case when T2.second is null then 'no' else 'yes' end) as yesOrno from T as T1 left join T as T2
on T1.First=t2.second
check sql fiddle : SQL Fiddle
You can do it like this:
declare #t table (
C1 char(1),
C2 char(1)
)
insert #t
values ('A','B'),
('C','D'),
('E','A'),
('X','C')
select t1.C1,t1.C2, case when t2.C2 is null then 'No' else 'Yes' end YesOrNo
from #t t1 left join #t t2
on t1.C1 = t2.C2
There are many different ways of writing this basic query.

Execute different statements in one query on the condition

Say we have two Users with ID = 1 and ID = 2
I know the ID of the current User and I need to execute different select statements depending on the ID.
if ID = 1
select a from table1
else if ID = 2
select b from table2
else
select c from table3
Is there a way to put this logic into single SQL query?
You can use union with appropriate where conditions.
select a from table1 where id = 1
union all
select b from table2 where id = 2
union all
select c from table3 where id not in (1,2)
or if the tables can be joined
select
case when t1.id = 1 then t1.a
when t2.id = 2 then t2.b
else t3.c end
from table1 t1
join table2 t2 on t1.id = t2.id
join table3 t3 on t1.id = t3.id

Alternative for union in Oracle

Is there any alternate way to fetch the following data without using union?
select A.name,A.age,B.Address,C.phoneNo from table1 A,Table2 B,Table3 C where a.pkId = b.FkId and b.pkId = c.FkId
union
select A.name,A.age,B.Address,C.phoneNo from table4 A,Table5 B,Table3 C where a.pkId = b.FkId and b.pkId = c.FkId
I am using this in Hibernate and unfortunately hibernate doesnt support Union. I was just wondering if there is any other way to achieve it else ill have to write it in a procedure and save the data in temp table and fire a sql to read data from that temp table
There is an alternative for union, but it is not pretty:
select distinct coalesce(x1.name, x2.name) as name,
coalesce(x1.age, x2.age) as age,
coalesce(x1.Address, x2.Address) as age,
coalesce(x1.phoneNo, x2.phoneNo) as age,
from (select A.name, A.age, B.Address, C.phoneNo
from table1 A join
Table2 B
on a.pkId = b.FkId join
Table3 C
on b.pkId = c.FkId
) x1 full outer join
(select A.name, A.age, B.Address, C.phoneNo
from table4 A join
Table5 B
on a.pkId = b.FkId join
Table3 C
on b.pkId = c.FkId
) x2
on 1 = 0; -- always false
I can't imagine why you would want to express a union like this. I would highly recommend, though, that you start using proper, explicit join syntax.
is this working ?
SELECT
CASE DISTINCT_FLG WHEN 1 THEN nameA ELSE nameB END name,
CASE DISTINCT_FLG WHEN 1 THEN ageA ELSE ageB END age,
CASE DISTINCT_FLG WHEN 1 THEN AddressA ELSE AddressB END Address,
CASE DISTINCT_FLG WHEN 1 THEN phoneNoA ELSE phoneNoB END phoneNo
FROM (
SELECT
T1.name AS nameA, T1.age AS ageA, T2.Address AS AddressA, T3.phoneNo AS phoneNoA,
T4.name AS nameB, T4.age AS ageB, T5.Address AS AddressB, T3.phoneNo AS phoneNoB,
ROW_NUMBER() OVER(PARTITION BY T1.name, T1.age, T2.Address, T4.name, T4.age, T5.Address, T3.phoneNo ORDER BY NULL) AS DISTINCT_FLG
FROM
table1 T1,
table2 T2,
table4 T4,
table5 T5,
table3 T3
WHERE
T1.pkId = T2.FkId AND
T4.pkId = T5.FkId AND
(
T2.pkId = T3.FkId OR
T5.pkId = T3.FkId
)
) WHERE DISTINCT_FLG IN (1, 2)
Those two UNION parts have Table3 C in common, so we can join the rest to it. To emulate UNION records from the source table can be replicated through unconditional cross join of an auxiliary table with the required number or rows:
Select Distinct
CASE R.r WHEN 1 THEN A1.name ELSE A2.name END As name ,
CASE R.r WHEN 1 THEN A1.age ELSE A2.age END As age ,
CASE R.r WHEN 1 THEN B1.Address ELSE B2.Address END As Address,
C.phoneNo
From Table3 C, --< Start at common Table3
(Select Rownum r From USER_TABLES Where Rownum < 3) R --< Two rows to replicate Table3 C
-- Any table with more than one row will do
-- USER_TABLES should have enough rows in this particular case
Left Join Table2 B1 On R.r = 1 AND B1.pkId = C.FkId --< Left Join branch one
Left Join table1 A1 On R.r = 1 AND A1.pkId = B1.FkId
Left Join Table5 B2 On R.r = 2 AND B2.pkId = C.FkId --< Left Join branch two
Left Join table4 A2 On R.r = 2 AND A2.pkId = B2.FkId
Where (R.r = 1 AND A1.pkId Is NOT NULL) --/ Make sure we have values
OR (R.r = 2 AND A2.pkId Is NOT NULL) --\ for the branch
But really, consider a view.

Update Fields - SQL Server

In SQL Server, I am trying to update null fields in a table with existing vales in the table.
Example:
Table has 4 columns:A,B,C,D
A B C D
1 2 3 4
5 Null Null 4
How can I populate the Null values with the values in B,C where D=4
Update Table
Set B=B
Where B is null
and D=4
One option is to use a self join:
update t
set t.b = t2.b
from yourtable t
join yourtable t2 on t.d = t2.d
and t2.b is not null
where t.b is null
What if multiple records exist for b grouped by d where b is not null? That could mess this up. Instead you'd have to decide which value to use. Here's an example choosing the min:
update t
set t.b = t2.b
from yourtable t
join (select d, min(b) b
from yourtable
where b is not null
group by d) t2 on t.d = t2.d
where t.b is null
Or with a correlated subquery:
update yourtable t
set b = (select min(b) from yourtable t2 where t.id = t2.id)
where t.b is null
A lot of options here...