What I intend to do?
To update a few target table fields for sub-set of matched target records, getting matched between source and target, provided they both being the same table.
Where I need help?
Merge-into-target-using-select-source-on- clause seems to have control only for two categories-
When Source and Target records match, update all matching target records
When Source and Target records does not match, insert or perform other control operations.
In my case, When Source and Target records match, I'd like to perform update on Not all records of target but on a sub-set of target records.
Requesting help to guide on this.
For reference here's the code(target filter qualifier commented, as it won't work for sure):
MERGE INTO TGT
USING (
SELECT id, account_number, part_role, inc_val, pay_frequency,
period, pay_option, inclusion_value
FROM Table_1
WHERE id = var1
AND account_number = var2
AND part_role in ('YY','XX')
) SRC
ON (
SRC.id = TGT.id
AND SRC.account_number = TGT.account_number
--TGT.part_role in ('AA','BB','CC','DD','EE') --This must be a wrong place for this qualifier, please help on where to include this qualifier for filtering out target records for update purpose
)
WHEN MATCHED THEN
UPDATE SET
TGT.inc_val = SRC.inc_val
,TGT.pay_frequency = SRC.pay_frequency
,TGT.period = SRC.period
,TGT.pay_option = SRC.pay_option
,TGT.inclusion_value = SRC.inclusion_value;
Other Associated Details
Database: Oracle
Version: 11gR2
Environment: Unix
Add where clause after SET statements.
MERGE INTO TGT
USING (SELECT
id,
account_number,
part_role,
inc_val,
pay_frequency,
period,
pay_option,
inclusion_value
FROM Table_1
WHERE id = var1
AND account_number = var2
AND part_role IN ('YY', 'XX')) SRC
ON (
SRC.id = TGT.id
AND SRC.account_number = TGT.account_number
--TGT.part_role in ('AA','BB','CC','DD','EE') --This must be a wrong place for this qualifier, please help on where to include this qualifier for filtering out target records for update purpose
)
WHEN MATCHED THEN
UPDATE SET
TGT.inc_val = SRC.inc_val
, TGT.pay_frequency = SRC.pay_frequency
, TGT.period = SRC.period
, TGT.pay_option = SRC.pay_option
, TGT.inclusion_value = SRC.inclusion_value
WHERE TGT.part_role in ('AA','BB','CC','DD','EE');
Related
This query properly updates all records with a matched name and null target key -
MERGE
`MY_TAGET_TABLE` AS Target
USING
(
select
distinct name, key
from
`MY_SOURCE_TABLE`
)
AS Source
ON Source.name = Target.name
WHEN MATCHED and (Target.key is null) THEN UPDATE SET
Target.key = Source.key,
Target.load_time = CURRENT_TIMESTAMP()
This query never updates any records -
MERGE
`MY_TAGET_TABLE` AS Target
USING
(
select
distinct name, key
from
`MY_SOURCE_TABLE`
)
AS Source
ON Source.name = Target.name
WHEN MATCHED and (Target.key <> Source.key) THEN UPDATE SET
Target.key = Source.key,
Target.load_time = CURRENT_TIMESTAMP()
My source has all non-null key values. The first query is just a POC to show that the rest of the query is working and for some reason the (Target.key <> Source.key) part of the matched query causes no records to get updated although there records with matching name and non-matching key values. If I instead use Target.key is null it will update the records, although this doesn't account for all of my use-cases (when the Target key is out of sync with the Source key)
The goal is to upsert data from original_table into the target table using stage temp table. Upserting works fine. The problem I'm having is that after upserting I'd like to modify versions timestamps in the target but only for ids that were in the stagged table.
Queries below is roughly what I have. When removing the WHERE from the last update, i.e WHERE t.id in (SELECT DISTINCT id from stage) all works as intended. However, we're expecting billions of rows so doing this every couple of hours is not feasible. (Yes, subquery will be changed into INNER JOIN to optimize performance.)
Any idea what's going on? Why there are no rows in the target with id (in stage) even though I just copied over that table?
-- Temp table
CREATE TEMP TABLE stage (LIKE target);
-- Lift recent data from one table and put it into stage
INSERT INTO stage SELECT {transformations} FROM original_table WHERE version_start > current_day - 1;
-- Update overlaps in the stage table with ids that are in target
UPDATE stage
SET id = target.id
FROM target WHERE stage.service_id = target.service_id AND stage.region = target.region;
-- Update unique row_id (per id and version)
UPDATE stage
SET row_id = target.row_id
FROM target WHERE stage.id = target.id AND stage.timestamp_start = target.timestamp_start;
-- Delete all duplicate entries
DELETE FROM target USING stage WHERE stage.row_id = target.row_id;
-- Copy over all staged data into cleaned target
INSERT INTO target SELECT * FROM stage s;
-- Update entries in the 'target' to have {current_row}.version_start = {previous_row}.version_end.
-- Look only for ids that were in the stage table.
UPDATE target
SET timestamp_end = versions.timestamp_end
FROM (
SELECT
t.row_id, t.id, t.timestamp_start,
lead(t.timestamp_start) over (partition by t.id order by t.timestamp_start asc) as timestamp_end
FROM target t
WHERE t.id in (SELECT DISTINCT id from stage)
) versions
WHERE target.row_id = versions.row_id;
I have two databases.
Alarm
TMP
I have a table in Alarm, where in a table there is one empty column with null values.
And I have a single column table in TMP.
I want to copy this single column values to my table in Alarm database.
What I tried so far is,
update [Alarm].[dbo].[AlarmDetails] set Alarm_Message = (select * from [TMP].[dbo].[AlarmDetails$])
where 1=1
The error is
Subquery returned more than 1 value.
Please note this,
NOTE: There is no id column in source table. Only one table & one column, Alarm Message.
I know the cause of error, but how should I modify my SQL.
Thank You.
Here's an example of copying a column:
update dst
set Alarm_Message = src.AlarmMessage
from Alarm.dbo.AlarmDetails dst
join TMP.dbo.AlarmDetails src
on dst.id = src.id
You did not specify how the tables are related, so I assumed they both have an id column.
You need something like this.
update t1
set
t1.<something1> = t2.<something2>
from
[Alarm].[dbo].[AlarmDetails] t1
join [TMP].[dbo].[AlarmDetails] t2 on (t1.<cols1> = t2.<cols2>)
UPDATE results SET results.platform_to_insert = (
SELECT correct_platform
FROM build
WHERE results.BuildID=build.BuildID LIMIT 1
);
I am trying to merge two tables and I would like to use GROUP BY in order to fix the following error:
The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row. A MERGE statement cannot UPDATE/DELETE the same row of the target table multiple times. Refine the ON clause to ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.
Where exactly would the GROUP BY clause go?
MERGE dbo.MyTarget targ
USING dbo.MySource src
ON (targ.Identifier = src.Identifier
AND targ.Name = src.ConstituentName
AND targ.Ticker = src.ConstituentTicker
AND (targ.CUSIP = src.CUSIP OR targ.ISIN = src.ISIN OR targ.SEDOL = src.SEDOL))
WHEN MATCHED THEN
-- update values
;
Something like this:
MERGE dbo.MyTarget targ
USING (SELECT ... FROM dbo.MySource GROUP BY .....) src
ON (targ.Identifier = src.Identifier
AND targ.Name = src.ConstituentName
AND targ.Ticker = src.ConstituentTicker
AND (targ.CUSIP = src.CUSIP OR targ.ISIN = src.ISIN OR targ.SEDOL = src.SEDOL))
WHEN MATCHED THEN
-- update values
;
I am trying to insert some data from one table into another but I would like to prevent the insertion of duplicate rows. I have currently the following query:
INSERT INTO Table1
(
Table1Col1,
Table1Col2,
Table1Col3,
Table1Col4,
Table1Col5
)
SELECT
Table2Col1,
Table2Col2 = constant1,
Table2Col3 = constant2,
Table2Col4 = constant3,
Table2Col5 = constant4
FROM Table2
WHERE
Condition1 = constant5
AND
Condition2 = constant6
AND
Condition3 = constant7
AND
Condition4 LIKE '%constant8%'
What I do not know is that the row I am trying to insert from Table2 into Table1 might already exist and I would like to prevent this possible duplication from happening and skip the insertion and just move onto inserting the next unique row.
I have seen that I can use a WHERE NOT EXISTS clause and use of the INTERSECT keyword but I did not fully understand how to apply it to my particular query as I only want to use some of the selected data from Table2 and then some constant values to insert into Table1.
EDIT:
I should add that the columns TableCol2 through to TableCol5 don't actually exist in the result set and I am just populating these columns alongside Table2Col1 that is returned.
Since you are on SQL Server 2008, you can use a merge statement.
You can easily check if a row exists base on a key
something like this:
merge TableMain AS target
using TableA as source
ON <join tables here>
WHEN MATCHED THEN <update>
WHEN NOT MATCHED BY TARGET <Insert>
WHEN NOT MATCHED BY SOURCE <delete>
Intersect (minus in Sql Server's terms) is out of question because it compares whole row. Other two options are not in/not exists/left join and merge. Not In is for single-column prinary key only, so it is out of question in this instance. In/Exists/Left join should have the same performance in Sql Server, so I'll just use exists:
INSERT INTO Table1
(
Table1Col1,
Table1Col2,
Table1Col3,
Table1Col4,
Table1Col5
)
SELECT
Table2Col1,
Table2Col2 = constant1,
Table2Col3 = constant2,
Table2Col4 = constant3,
Table2Col5 = constant4
FROM Table2
WHERE
Condition1 = constant5
AND
Condition2 = constant6
AND
Condition3 = constant7
AND
Condition4 LIKE '%constant8%'
AND NOT EXISTS
(
SELECT *
FROM Table1 target
WHERE target.Table1Col1 = Table2.Table2Col1
AND target.Table1Col2 = Table2.Table2Col2
AND target.Table1Col3 = Table2.Table2Col3
)
Merge is used to sync two tables; it has ability to insert, update and delete records from target table.
merge into table1 as target
using table2 as source
on target.Table1Col1 = source.Table2Col1
AND target.Table1Col2 = source.Table2Col2
AND target.Table1Col3 = source.Table2Col3
when not matched by target then
insert (Table1Col1,
Table1Col2,
Table1Col3,
Table1Col4,
Table1Col5)
values (Table2Col1,
Table2Col2,
Table2Col3,
Table2Col4,
Table2Col5);
If columns from table2 are computed during transfer, in not exists() case you might use derived table in place of table2, and the same applies to merge example - just place your query in place of reference to table2.
we have check the whether the data is already exist or not in table. For this we have to use If condition to avoid the duplicate insertion