Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 INSERT based on three fields

Author  Topic 

yosiasz
Master Smack Fu Yak Hacker

1635 Posts

Posted - 2009-04-08 : 15:53:50
Hi,

For Following table
BackLog
BackLogID
CommodityID
DefinitionValue
DefinitionDate
BranchID
UserDate
UserName
I need to do an INSERT only if three fields (DefinitionDate
,BranchID and CommodityID) do not EXIST in the target table. If those fields exist then do an UPDATE if and only if the value of one field (DefinitionValue) has changed. How can I do that. Most examples I see do the EXISTS but it does not fit my situation. I haev tried LEFT OUTER JOIN but is a performance hogger.

Thanks

<><><><><><><><><><><><><><><><><><><><><><><><><>
If you don't have the passion to help people, you have no passion

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2009-04-08 : 15:55:45
Do it three steps, because you don't have MERGE command for SQL Server 2005
UPDATE		t
SET t.Accum = t.Accum + s.Value
FROM tblTarget AS t
INNER JOIN (
SELECT DefinitionDate,
BranchID,
CommodityID,
ROW_NUMBER() OVER (PARTITION BY DefinitionDate, BranchID, CommodityID ORDER BY DefinitionDate) AS recID,
Value
FROM tblSource
) AS s ON s.DefinitionDate = t.DefinitionDate
AND s.BranchID = t.BranchID
AND s.CommodityID = t.CommodityID
WHERE s.recID = 1

INSERT tblTarget
(
DefinitionDate,
BranchID,
CommodityID,
Value
)
SELECT s.DefinitionDate,
s.BranchID,
s.CommodityID,
s.Value
FROM (
SELECT DefinitionDate,
BranchID,
CommodityID,
ROW_NUMBER() OVER (PARTITION BY DefinitionDate, BranchID, CommodityID ORDER BY DefinitionDate) AS recID,
Value
FROM tblSource
) AS s
WHERE s.recID = 1
AND NOT EXISTS (
SELECT *
FROM tblTarget AS t
WHERE t.DefinitionDate = s.DefinitionDate
AND t.BranchID = s.BranchID
AND t.CommodityID = s.CommodityID
)

UPDATE t
SET t.Accum = t.Accum + s.Value
FROM tblTarget AS t
INNER JOIN (
SELECT DefinitionDate,
BranchID,
CommodityID,
ROW_NUMBER() OVER (PARTITION BY DefinitionDate, BranchID, CommodityID ORDER BY DefinitionDate) AS recID,
Value
FROM tblSource
) AS s ON s.DefinitionDate = t.DefinitionDate
AND s.BranchID = t.BranchID
AND s.CommodityID = t.CommodityID
WHERE s.recID > 1



E 12°55'05.63"
N 56°04'39.26"
Go to Top of Page

yosiasz
Master Smack Fu Yak Hacker

1635 Posts

Posted - 2009-04-08 : 16:12:43
Thanks Peter! I will try that out. Only question though will this only update if value has changed, or will it update anyways even if value is the same. Which is no problem if it does.

<><><><><><><><><><><><><><><><><><><><><><><><><>
If you don't have the passion to help people, you have no passion
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2009-04-08 : 16:14:19
SQL Server 2008
DECLARE	@Target TABLE
(
a INT,
b INT,
c INT,
i INT
)

INSERT @Target
SELECT 1, 1, 1, 100

DECLARE @Source TABLE
(
a INT,
b INT,
c INT,
i INT
)

INSERT @Source
SELECT 1, 1, 1, 50 UNION ALL
SELECT 3, 3, 3, 10 UNION ALL
SELECT 2, 2, 2, 45 UNION ALL
SELECT 2, 2, 2, 40

-- Peso
MERGE @Target AS t
USING (
SELECT a,
b,
c,
SUM(i) AS i
FROM @Source
GROUP BY a,
b,
c
) AS s ON s.a = t.a
AND s.b = t.b
AND s.c = t.c
WHEN MATCHED THEN UPDATE SET t.i += s.i
WHEN NOT MATCHED THEN INSERT (a, b, c, i) VALUES (a, b, c, i);

SELECT *
FROM @Target



E 12°55'05.63"
N 56°04'39.26"
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2009-04-08 : 16:18:30
Another SQL Server 2000/2005 approach
DECLARE	@Target TABLE
(
a INT,
b INT,
c INT,
i INT
)

INSERT @Target
SELECT 1, 1, 1, 100

DECLARE @Source TABLE
(
a INT,
b INT,
c INT,
i INT
)

INSERT @Source
SELECT 1, 1, 1, 50 UNION ALL
SELECT 3, 3, 3, 10 UNION ALL
SELECT 2, 2, 2, 45 UNION ALL
SELECT 2, 2, 2, 40

-- Peso
UPDATE t
SET t.i = t.i + s.i
FROM @Target AS t
INNER JOIN (
SELECT a,
b,
c,
SUM(i) AS i
FROM @Source
GROUP BY a,
b,
c
) AS s ON s.a = t.a
AND s.b = t.b
AND s.c = t.c

INSERT @Target
(
a,
b,
c,
i
)
SELECT a,
b,
c,
i
FROM (
SELECT a,
b,
c,
SUM(i) AS i
FROM @Source
GROUP BY a,
b,
c
) AS s
WHERE NOT EXISTS (SELECT * FROM @Target AS x WHERE x.a = s.a AND x.b = s.b AND x.c = s.c)

SELECT *
FROM @Target



E 12°55'05.63"
N 56°04'39.26"
Go to Top of Page

yosiasz
Master Smack Fu Yak Hacker

1635 Posts

Posted - 2009-04-08 : 16:51:06
Peso

For your post Posted - 04/08/2009 : 15:55:45. What is the second UPDATE for where RecID > 1?

Thanks

<><><><><><><><><><><><><><><><><><><><><><><><><>
If you don't have the passion to help people, you have no passion
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2009-04-08 : 17:50:26
Because if there are duplicate records in @Source over the three key columns.
But never mind that suggestion. The suggestion posted 04/08/2009 : 16:18:30 takes care of that.



E 12°55'05.63"
N 56°04'39.26"
Go to Top of Page

yosiasz
Master Smack Fu Yak Hacker

1635 Posts

Posted - 2009-04-08 : 18:01:27
Thank you! There won't be (should not be ) aduplicate rows over the three keys in my case. I will take a look at the post you refer.

<><><><><><><><><><><><><><><><><><><><><><><><><>
If you don't have the passion to help people, you have no passion
Go to Top of Page

yosiasz
Master Smack Fu Yak Hacker

1635 Posts

Posted - 2009-04-09 : 11:56:01
Wow, wow wow. Peso, thank you very much this worked perfectly! Appreciate the help!

<><><><><><><><><><><><><><><><><><><><><><><><><>
If you don't have the passion to help people, you have no passion
Go to Top of Page
   

- Advertisement -