SQL update with aggregate in WHERE clause - sql

I'm trying to set the date field for column date to let's say '10/11/2012' in table 1 when the sum of all amounts table 2 related to that id (via fk_id) = 0. Here's what I mean:
FROM:
table 1
id date
1 10/11/2011
2
3 10/12/2011
table 2
fk_id amount
1 200
2 0
2 0
3 100
TO:
table 1
id date
1 10/11/2011
2 10/11/2012
3 10/12/2011
table 2
fk_id amount
1 200
2 0
2 0
3 100
This is what I have currently:
update table1
set date = '10/11/2012
FROM table1 inner join table 2 on table1.id = table2.fk_id
HAVING sum(table2.amount) = 0
Can someone help me out here?

UPDATE table1
SET date = '10/11/2012'
FROM table1
WHERE id IN (SELECT FK_ID FROM table2 GROUP BY FK_ID HAVING SUM(Amount)=0)

This should work:
UPDATE T1
SET [date] = '20121011'
FROM table1 T1
INNER JOIN (SELECT fk_id, SUM(amount) Amount
FROM table2
GROUP BY fk_id
HAVING SUM(amount) = 0) T2
ON T1.id = T2.fk_id

Related

Join 2 tables with classification tag in one column

I have a SQL Table in Oracle. I have to join 2 tables (One with ID and other data, second with ID and date in each row, second table is displayed below) but dont want get joined data from the second table but only tag (1 or 0 based on the condition that searching ID has a date between 21/08/01 to 21/08/31).
Table 2
# ID Date
# 1 21/08/01
# 2 21/07/02
# 3 21/08/24
# 4 21/08/02
# 5 21/06/03
# 6 21/08/05
# 7 21/08/26
# 8 21/08/05
My desired output should look like:
Table 1
# ID Date Other data
# 1 1 ....
# 2 0 ....
# 3 1 ....
# 4 1 ....
# 5 0 ....
# 6 1 ....
# 7 1 ....
# 8 1 ....
Anyone can help?
Looks like CASE to me:
with temp_2 as
(select b.id,
b.name,
b.address,
b.date_column,
rank() over (partition by b.id order by b.date_column desc) rnk
from table_2 b
)
select
a.id,
a.some_other_column,
--
case when b.date_column between date '2021-08-01' and date '2021-08-31' then 1
else 0
end as tag
from table_1 a left join temp_2 b on a.id = b.id and b.rnk = 1
If there is only one id in table2, you can use left join:
select t`.*,
(case when t2.date is null then 0 else 1 end) as flag
from table1 t1 left join
table2 t2
on t2.id = t1.id and
t2.date between date '2021-08-01' and date '2021-08-31;
A more general solution that works for multiple matches in table2 is exists:
select t.*,
(case when exists (select 1
from table2 t2
where t2.id = t1.id and
t2.date between date '2021-08-01' and date '2021-08-31'
)
then 1 else 0
end) as flag
from table1 t1

Update row in TABLE1 using value from another row in TABLE1 to lookup value in TABLE2

I have a table as follows
TABLE1
Id UserId Type Value
1 AAA companyid 123
2 AAA branchid
3 BBB companyid 124
4 BBB branchid
5 CCC companyid 125
6 CCC branchid
and TABLE2
BranchId CompanyId Name
1 123 RedBranch
2 123 YellowBranch
3 123 GreenBranch
4 124 SouthBranch
5 125 NorthBranch
I need to update Type in TABLE1 WHERE Type = 'branchid' using the value in Type = 'companyid' for the same UserId. Once I have the correct 'companyid' I want to use the following SELECT to get the TOP BranchId from TABLE2
SELECT TOP 1 Id
FROM TABLE2
WHERE CompanyId = (correct companyid from TABLE1)
ORDER BY Id DESC
How can I achieve this in one Update statement?
Here's a stab at it:
update T1
set Value = (select max(BranchId) from Table2 where CompanyId = T1a.value)
from Table1 T1
inner join Table1 T1a on T1a.UserId = T1.UserId and T1a.Type = 'companyid'
where T1.Type = 'branchid'
I'm not sure that I fully understand the quesion, but maybe...
with maxBranch as
(
select
max(BranchId) as BranchId
,CompanyId
from TABLE2
group by CompanyId
)
update t1
set t1.Value = m.BranchID
from TABLE1 as t1
join TABLE1 as t11
on t1.UserId = t11.UserId
and t1.Type = 'branchid'
and t11.Type = 'companyid'
join maxBranch as m
on m.CompanyId = t11.Value

Return id when id value does not equal 0 at least once

I have 2 tables.
table_1
id | product
1 | a
2 | b
3 | c
4 | d
table_2
product_id | value
1 | 0
2 | 0
1 | 5
2 | 0
4 | 10
How can I return details from table_1 for ids that:
- are present in table_2 (table_1.id = table_2.product_id)
- do not have any associated value equal to 0 (for example id "1" should be excluded)
The correct result would be id "4" as none of its values equal to zero.
I have tried below query but it returns also id "3" that is not present in the table_2.
SELECT * FROM table_1
WHERE id NOT IN (
SELECT product_id FROM table_2
WHERE value = 0)
You can use two conditions:
SELECT t1.*
FROM table_1 t1
WHERE EXISTS (SELECT 1
FROM table_2 t2
WHERE t1.id = t2.product_id
) AND
NOT EXISTS (SELECT 1
FROM table_2 t2
WHERE t1.id = t2.product_id AND t2.value = 0
);
The naive approach:
-- Step 1: Select product IDs to ignore
SELECT product_id
FROM table_2
WHERE value = 0
-- Step 2: Select product IDs to include
SELECT product_id
FROM table_2
WHERE product_id NOT IN ( -- Use the result of Step 1
SELECT product_id
FROM table_2
WHERE value = 0
)
-- Final query: Select products
SELECT *
FROM table_1
WHERE product_id IN ( -- Use the result of Step 2
SELECT product_id
FROM table_2
WHERE product_id NOT IN ( -- Use the result of Step 1
SELECT product_id
FROM table_2
WHERE value = 0
)
)
One option, using aggregation:
SELECT
t1.id,
t1.product
FROM table_1 t1
INNER JOIN table_2 t2
ON t1.id = t2.product_id
GROUP BY
t1.id,
t1.product
HAVING
COUNT(CASE WHEN t2.value = 0 THEN 1 END) = 0;
In order for the HAVING clause to return true, the product must not have had any zero value in the second table. Also, the inner join filters off any product which does not appear at all in the second table.
You can get the ids you need to use for the IN clause, by grouping by product_id and putting the condition in the HAVING clause:
SELECT * FROM table_1
WHERE id IN (
SELECT product_id
FROM table_2
GROUP BY product_id
HAVING SUM(CASE WHEN value = 0 THEN 1 ELSE 0 END) = 0
)

Updating sum in a column in first table with data from other table

I have table1 as below:
Col1 Bal
-------------------
1 0
2 0
3 0
4 0
Col1 is the key here.
I have table2 as below:
Col1 Bal Date
---------------------
1 5 x
1 10 y
1 7 z
3 8 p
3 9 m
Col1 is the join column in both tables.
I want to update bal in first table with sum of bal in 2nd table.
What would be the sql statement for this:
update table1 a set a.bal=(select sum(b.bal) from table2) where
and I am lost!
After update, table1 should be:
Col1 Bal
-------------------
1 22
2 0
3 17
4 0
From the documentation, it looks like you can use table aliases in DB2:
update table1 a
set bal = coalesce(
(
select sum(b.bal)
from table2 as b
where a.col1 = b.col1
), 0)

Design SQL Query for following case

Consider tables
Table1
id, name
1 xyz
2 abc
3 pqr
Table2
id title
1 Mg1
2 Mg2
3 SG1
Table3
Tb1_id tb2_id count
1 1 3
1 2 3
1 3 4
2 2 1
3 2 2
3 3 2
I want to do query to give result like
id title
1 MG1
2 MG2
3 Two or More Title
MG1 has higher preference if MG1 and count >= 1 then it is given as MG1 title , for others corresponding title is used and for count > 1 as two or more
I think this is what you are going for:
select t3.Tb1_id as id,
case
when mg1cnt.count >= 1 then 'MG1'
when cnt.count = 1 then upper(t2.title)
else 'Two or More Titles'
end as title
from (
select Tb1_id, count(*) as count
from Table3
group by Tb1_id
) cnt
inner join (
select Tb1_id, isnull(SUM(case when t2.title='mg1' then 1 end), 0) as count
from Table3 t3
inner join Table2 t2 on t3.tb2_id = t2.id
group by Tb1_id
) as mg1cnt on cnt.Tb1_id = mg1cnt.Tb1_id
inner join Table3 t3 on cnt.Tb1_id = t3.Tb1_id
inner join Table2 t2 on t3.tb2_id = t2.id
group by t3.Tb1_id,
case
when mg1cnt.count >= 1 then 'MG1'
when cnt.count = 1 then upper(t2.title)
else 'Two or More Titles'
end