How to Update Value of One table using Another Table - snowflake-cloud-data-platform

I have two snowflake tables called as TABLE1 and TABLE2. I would like to update the rows of Table1 by Table2 only if some field values match with table2.
Table1
Date columnA columnB sum reff
2021-09-27 1 Y 10 A
2021-09-27 2 Y 20 B
2021-09-27 3 Y 30 C
2021-09-27 4 Y 40 D
2021-09-27 5 S 8000 D
Table2
Date columnA columnB sum reff
2021-09-27 5 Y 10 A
2021-09-27 2 Y 100 B
2021-09-27 3 Y 100 C
2021-09-27 4 Y 100 D
2021-09-27 6 S 8000 D
I want to Update rows if fields Date, columnA, columnB, reff are Matching in both tables (Update of rows should be in Table1)
Excepted output
Date columnA columnB sum reff
2021-09-27 1 Y 10 A
2021-09-27 2 Y 100 B
2021-09-27 3 Y 100 C
2021-09-27 4 Y 100 D
2021-09-27 5 S 8000 D
2021-09-27 5 Y 10 A
2021-09-27 6 S 8000 D
can someone help me please. Using select query to get the Excepted output

Snowflake merge also will work to get expected output:
merge into source1 a
using source2 b
on
a.date = b.date and
a.ColumnA = b.ColumnA and
a.ColumnB = b.ColumnB and
a.reff = b.reff
when matched then
update set
a.date = b.date,
a.ColumnA = b.ColumnA,
a.ColumnB = b.ColumnB,
a.sum = b.sum,
a.reff = b.reff
when not matched then insert
(a.date, a.ColumnA, a.ColumnB, a.sum, a.reff) values (b.date, b.ColumnA, b.ColumnB, b.sum, b.reff);

what you need is a full outer join.
this will join rows on your matching condition, but it will keep rows that don't have any matches (rows that don't need to get updated in table 1 AND rows that are new in table2).
when the join is not successful, you want to use whichever is not null.
when the join is successful, you want to use the values from table 2
This should do the trick I think:
select
IFNULL(t2.Date, t1.Date) as Date,
IFNULL(t2.columnA, t1.columnA) as columnA,
IFNULL(t2.columnB, t1.columnB) as columnB,
IFNULL(t2.sum, t1.sum) as sum,
IFNULL(t2.reff, t1.reff) as reff
from
Table2 t2
full outer join
Table1 t1
on t2.Date = t1.Date and t2.columnA = t1.columnA and t2.columnB = t1.columnB and t2.reff = t1.reff
Another option to update table1 in place would be to use a merge statement. Updating on a match and inserting a record when not matched.

Related

how to delete repeated successive rows SQL

i have history table with many rows T1, i need information from 3 rows so i have new table T2, and i want copy this information from T1 to T2.
but i have duplicate data ,so how copy right ?
some duplicate rows i need and some not .only if on column D i have same data like rows before i don't need info from this row
example:
i have table looks like this -
T1:
Id B D
1 8 10
2 8 3
3 8 3
4 8 10
i need this rows only -
T2:
Id B D
1 8 10
2 8 3
4 8 10
Just compare with the previous row data, if match then do not include it by where condition
;WITH data AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY Id) AS Sequence FROM [Table]
)
SELECT Id, B, D
FROM data d
WHERE
NOT EXISTS
(
SELECT *
FROM data
WHERE Sequence + 1 = d.Sequence
AND B = d.B
AND D = d.D
)
insert into t2
select Id ,B ,D
(select * from t2
except
select d* from t1) t3

Joining two SQL tables based on the equality of few columns

I am trying to Create a SQL View by joining two SQL tables and return only the lowest value from second table and all the rows from first table similar to left join.
My problem can be clearly explained with the below example.
Table1
Id Product Grade Term Bid Offer
100 ABC A Q1 10 20
101 ABC A Q1 5 25
102 XYZ A Q2 25 30
103 XYZ B Q2 20 30
Table2
Id Product Grade Term TradeValue
1 ABC A Q1 100
2 ABC A Q1 95
3 XYZ B Q2 100
In the above data I want to join Table1 and Table2 when ever the columns Product,Grade and Term from both the tables are equal and return all the rows from Table1 while joining the lowest Value of the column TradeValue from Table2 to the first record of the match and making TradeValue as NULL for other rows of the resultant View and the resultant View should have the Id of Table2 as LTID
So the resultant SQL View should be
RESULT
Id Product Grade Term Bid Offer TradeValue LTID
100 ABC A Q1 10 20 95 2
101 ABC A Q1 5 25 NULL 2
102 XYZ A Q2 25 30 NULL NULL
103 XYZ B Q2 20 30 100 3
I tried using the following query
CREATE VIEW [dbo].[ViewCC]
AS
SELECT
a.Id,a.Product,a.Grade,a.Term,a.Bid,a.Offer,
b.TradeValue
FROM Table1 AS a
left JOIN (SELECT Product,Grade,Term,MIN(TradeValue) TradeValue from Table2 Group by Product,Grade,Term,) AS b
ON b.Product=a.Product
and b.Grade=a.Grade
and b.Term=a.Term
GO
The above Query returned the following data which is apt to the query I wrote but that is not what I was trying to get
Id Product Grade Term Bid Offer TradeValue
100 ABC A Q1 10 20 95
101 ABC A Q1 5 25 95 --This should be null
102 XYZ A Q2 25 30 NULL
103 XYZ B Q2 20 30 100
As we can see minimum value of TradeValue being assigned to all matching rows in Table1 and also I was not able to return Id As LTID from Table2 as I have issues with group by clause as I cannot group it by b.Id as it returns too many rows.
May I know a better way to deal with this?
You need a row number attached to each record from Table1, so that the requirement of only joining the first record from each group of Table1 can be fulfilled:
CREATE VIEW [dbo].[ViewCC]
AS
SELECT a.Id, a.Product, a.Grade, a.Term, a.Bid, a.Offer,
b.TradeValue, b.Id AS LTID
FROM (
SELECT *, ROW_NUMBER() OVER(PARTITION BY Product, Grade, Term ORDER BY Id) AS rn
FROM Table1
) a
OUTER APPLY (
SELECT TOP 1 CASE WHEN rn = 1 THEN TradeValue
ELSE NULL
END AS TradeValue, Id
FROM Table2
WHERE Product=a.Product AND Grade=a.Grade AND Term=a.Term
ORDER BY TradeValue) b
GO
OUTER APPLY returns a table expression containing either the matching record from Table2 with the lowest TradeValue, or NULL if no matching record exists.

Updating each row in a table

I have two tables both of which have a column named column_value which holds a number value. Now what i want is to sum the values of column_value in both the tables individually for each row and then update the same column (column_value) in the first table with the sum that i get for each row.
For example I have table A and table B, both of them have a column name AMOUNT.
Table A:
id AMOUNT
1 20
2 30
Table B:
id AMOUNT
1 10
2 25
First of all i want to get the following result
id AMOUNT AMOUNT TOTALAMOUNT
1 20 10 30
2 30 25 55
Now i would like to update each row of the A table with the TOTALAMOUNT against each id
so that after the Update the table A should look like
id AMOUNT
1 30
2 55
Selection :
SELECT A.ID,
NVL(A.AMOUNT,0) A_AMOUNT ,
NVL(B.AMOUNT,0) B_AMOUNT ,
NVL(A.AMOUNT,0) + NVL(B.AMOUNT,0) AS TOTAL_AMOUNT
FROM TABLEA A, TABLEB B
WHERE A.ID = B.ID
Update:
UPDATE TABLEA A
SET A.AMOUNT = (SELECT NVL(A.AMOUNT,0) + NVL(B.AMOUNT,0)
FROM TABLEB B
WHERE A.ID = B.ID)
You should have to use left join. For example:
Table_a
id val
1 10
2 20
Table_b
id val
1 20
2 30
update Table_a a left join Table_b b on a.id = b.id set a.val = (a.val+b.val);
After this operation:
Table_a
id val
1 30
2 50

Slow SQL query with SQL Server

I have two SQL queries to count co-occurrences between id2 values among different id1 values. The sample table looks like
id1 | id2
101 | 1
101 | 2
101 | 3
102 | 2
102 | 3
102 | 4
103 | 15
103 | 3
103 | 4
and the desired output is:
A B Count
1 2 1
1 3 2
2 3 4
1 4 2
2 4 3
3 4 4
1 15 1
2 15 2
3 15 2
4 15 1
Both solutions are pasted below.
-- Solution 1
SELECT bar.id2 AS A, foo.id2 AS B, COUNT(*) AS Count
FROM
(SELECT * FROM TestTab) AS bar,
(SELECT * FROM TestTab) AS foo
WHERE bar.id1 <> foo.id1
AND bar.id2 < foo.id2
GROUP BY bar.id2, foo.id2
-- Solution 2
SELECT bar.id2 AS A, foo.id2 AS B, COUNT(*) AS Count
FROM TestTab AS bar
JOIN TestTab AS foo
ON bar.id1 <> foo.id1
WHERE bar.id2 < foo.id2
GROUP BY bar.id2, foo.id2
Both queries work fine on small tables (i.e., 100 - 1000 rows), but I need to query much larger table (e.g., 100.000 rows). I wonder how to speed up the queries and improve performance. Thanks in advance for any pointers.
- Create table TestTab and insert dummy data
CREATE TABLE TestTab
INSERT INTO TestTab VALUES
(101,1),
(101,2),
(101,3),
(102,2),
(102,3),
(102,4),
(103,15),
(103,3),
(103,4)
I suggest adding an index on id2 to TestTab (if one doesn't already exist) and then try running the following:
select distinct id2 into #id2 from TestTab;
SELECT bar.id2 AS A, foo.id2 AS B, COUNT(*) AS Count
FROM #id2 AS bar
JOIN #id2 AS foo ON bar.id2 < foo.id2
JOIN TestTab AS buz ON bar.id2 = buz.id2
JOIN TestTab AS fuz ON foo.id2 = fuz.id2
WHERE buz.id1 <> fuz.id1
GROUP BY bar.id2, foo.id2;
(If you already have a table with the distinct values of id2 on it, skip creating the temporary table and use that instead.)
Both queries are joins and equivalent.
The first one is an implicit join with additional subselects. It might be slower, if SQL Server doesn't optimize the subselects away.
As others already observed, add indexes to the join condition column id1 and the where clause column id2, if you haven't done so already.

Get Sum of Count

The View obtains the first three columns. I need to add one more column (totalCount) to the view that obtains the total count:
CId CCId CCount totalCount
1 a 3 6
1 a 3 6
1 b 3 6
1 c 3 6
2 b 2 6
2 b 2 6
2 a 2 6
2 a 2 6
3 v 1 6
How to get the totalCount as 6?
(Business rule for Cid=1 Ccount=3 Cid=2 Ccount=2 Cid=3 Ccount=1 So the totalCount =3+2+1 =6)
SELECT a.CID, a.CCID, a.CCOUNT,
b.TotalCount
FROM Table1 a, (SELECT SUM(DISTINCT cCOunt) TotalCount
FROM Table1) b
SQLFiddle Demo
UPDATE
As Andomar pointed out on the comment, An update has been made on the query,
SELECT a.CID, a.CCID, a.CCOUNT,
b.TotalCount
FROM Table1 a,
(
SELECT SUM(TotalCount) TotalCount
FROM
(
SELECT MAX(cCOunt) TotalCount
FROM Table1
GROUP BY CId
) c
) b
SQLFiddle Demo
With this code I came to the desired result:
select CId
,CCId
,CCount
,(select SUM(a.tcount)
from (select distinct CId ,CCount as tcount
from dbo.Test) as a ) totalcount
from dbo.Test
From your example data, I'm assuming a Cid can only have one, possibly repeated, value of CCount. In that case you can pick a random one (say max) using a group by, and sum those:
select sum(OneCCCount) as TotalCount
from (
select max(CCount) as OneCCCount
from YourTable
group by
CId
) as SubQueryAlias

Resources