I'm trying to update a column in target table using merge statement by joining target table with source tables and getting the following error.
I need to compare a offer_id, order_Date and Doc_receipt_date from TRADE table with offer_trade_by_date, offer_start_date, offer_end_date. Here I'm trying to verify the trade is done with in the time period. If TRADE is done in time then it's pass the check (i.e 'Y'). If TRADE is not done in time then it didn't pass the check (i.e 'N'). If we don't have any information to check the condition (i.e when DOCK_RECEIPT_DATE is NULL) then ('X'). To achieve this check I wrote below code and getting the following error.
ORA: 30926 unable to get a stable set of rows in the source table.
Check the data in my tables below.
TRADE / Target table
KEYID DPBL_OFFER ORD_DATE DOC_RECPT_DT TRADE_DATE_MET
1 107 30-SEP-17 01-JAN-17 X
2 107 22-SEP-17 NULL X
3 107 07-OCT-17 NULL X
4 107 24-NOV-17 28-NOV-17 X
5 106 24-AUG-17 11-SEP-17 X
6 105 11-JUN-17 NULL X
7 108 05-SEP-17 13-SEP-17 X
8 109 28-JUL-17 10-AUG-17 X
9 110 01-SEP-17 14-SEP-17 X
PROD_OFFER /Source table)
Offer_id Trade_by_Date
106 14-OCT-17
107 14-NOV-17
105 02-AUG-17
108 18-NOV-17
109 14-OCT-17
110 18-NOV-17
OFFER_START_END_V /Source Table 2)
Offer_id Offer_Period Offer_Start_Date Offer_End_Date
106 1 27-JUL-17 27-JUL-17
106 2 28-JUL-17 14-OCT-17
107 1 15-SEP-17 23-JAN-18
105 1 01-JUN-17 02-AUG-17
108 1 23-AUG-17 14-SEP-17
108 2 16-SEP-17 19-SEP-17
110 1 23-AUG-17 14-SEP-17
110 2 16-SEP-17 19-SEP-17
109 1 02-JUL-17 12-NOV-17
Here keyid in my target table is PK and DPBL_OFFER id is offer_id from target table and isn't FK.
Check below code
MERGE INTO TRADE TB
USING (
SELECT T1.KEYID, T1.DPBL_OFFER
, CASE WHEN T1.ORD_DATE >= T3.OFFER_START_DATE AND
T1.ORD_DATE <= T2.TRADE_BY_DATE AND
T1.COD_RECPT_DATE <= T3.OFFER_END_DATE
THEN 'Y'
WHEN T1.ORD_DATE < T3.OFFER_START_DATE AND
T1.ORD_DATE > T2.TRADE_BY_DATE AND
T1.COD_RECPT_DATE > T3.OFFER_END_DATE
THEN 'N'
ELSE 'X'
END AS TRADE_DATE_MET
FROM TRADE T1
JOIN PROD_OFFER T2
ON T1.DPBL_OFFER_ID = T2.OFFER_ID
JOIN OFFER_START_END_V T3
ON T1.DPBL_OFFER_ID = T3.OFFER_ID) JT
ON TB.KEYID = JT.KEYID
AND TB.DPBL_OFFER_ID = JT.OFFER_ID
WHEN MATCH THEN
UPDATE SET TB. TRADE_DATE_MET = JT.TRADE_DATE_MET;
Can some one help me to overcome this error.?
FYI:- I'm using Oracle 11g.
That error generally means that there is at least one row in the target table (at least one, there may be many) for which there are at least TWO different rows in the source table (or result of three-table join, in your case) satisfying the ON condition(s) in the MERGE statement - and for which the values used in the UPDATE clause are actually different.
In your case: for KEYID = 5, DPBL_OFFER is 106. This joins to one row in PROD_OFFER and two different rows in OFFER_START_END_V. And the TRADE_END_MET is different for the two resulting rows in the three-table join. (Or, if it is the same - let's say 'N' for both - for this KEYID, then perhaps for KEYID= 7, with DPBL_OFFER = 108, which also joins to two different rows in the last table, the resulting TRADE_END_MET is not the same in both rows.)
This kind of error is usually fatal, since it is in fact an error in logic, regardless of code (or even of language). That is, even if you express the problem in common language and you try to solve it with paper and pencil, you can't, because it is self contradictory.
It is similar to, but more complicated than: Target table has columns ID (primary key) and FLAG (currently null). Source has columns ID and flag. Target has one row (1, null). Source has two rows, (1, 'Y') and (1, 'N'). You want to use the source to update the flag in the target. Do you see why that doesn't make sense? This is exactly the kind of problem you are having.
Run the three-way join by itself (the "source table" for the MERGE) and inspect the TRADE_END_MET values for KEYID = 5 and 7 - you will likely find the problem.
Related
I am trying to query a number of tables that have records with a one to many relationship. The records I need are the myid values with the following criteria:
They have to have the attribute
firstcode with values of 1, 3, 8, 200. It can be any combination of these codes or all of them.
secondstuff is also related to the firstcode; each firstcode will have a secondstuff value. The secondstuff values I am interested in are X, Y, Z (there are many others).
The problem I am running into is sometimes the myid record comes back, and it has 4 of the firstcode values, but not all of the firstcode values have the correct secondstuff value. Here is my query:
Select MYID
from myidtable a
where myid in (select myid1
from dadtable b
join momtable c
on b.dadid=c.momdadid
join kidtable d
on c.momid = d.kidid
where d.firstcode in (1, 3,8, 200)
and c.secondstuff in ('X', 'Y’, 'Z')
and thedate > to_date('12/31/2020', 'MM/DD/YYYY')
)
So in some cases I get a record back that has for example:
Myid firstcode secondstuff
34 1 X
34 3 M
34 8 X
As you can see, firstcode 3 has a secondstuff of M, as such, myid =34 shouldn’t be returned. What I am looking for is something like the following:
Myid firstcode secondstuff
35 1 X
35 3 Z
35 8 X
In this case, all my first codes that were associated with the myid table have the correct secondstuff values. Please note, its fine if some of the first code values are not associated with the myid table; Any two firstcodes will suffice.
From the information provided it seems that there are 2 columns with same name in two different tables. You are filtering in kidtable and while displaying you are accessing column from a different table. Make sure that you filter secondstuff column from all the tables in which it is present.
Given the output of a SELECT statement below, how would I update all records' "CameraLocationID" field to the value in the "LocationID" field?
Current State:
ItemID CameraID CameraLocationID LocationID
2 23038 NULL 335
3 23039 NULL 67
4 23040 NULL 34
5 23041 NULL 234
Desired Output:
ItemID CameraID CameraLocationID LocationID
2 23038 335 335
3 23039 67 67
4 23040 34 34
5 23041 234 234
What I've tried:
Selecting, and then trying to copy/paste single column using SSMS
An INSERT INTO (knowing pretty much this wouldn't work as I'm not really "INSERTING" per se
Copy and pasting the LocationID values into Excel, and then trying to c/p back into SQL using SSMS
Is there a SQL way of doing this fairly quickly?
EDIT: For future travelers, CameraLocationID and LocationID are in different tables. The SELECT brings them together into a single output before applying the UPDATE.
Update myTable set CameraLocationID = LocationID;
is all you need.
If locationID is coming from a different table you need an ID field there for linking, and I think the source and target both have CameraId field:
Update targetTable
set CameraLocationId = sourceTable.LocationId
from sourceTable
where targetTable.CameraID = sourceTable.CameraID;
If that is not the case, please supply full information on table structures and current data.
I have a single table with three columns, 'id', 'number' and 'transaction.' Each id should only be tied to one number however may exist many times in the table under different values of transaction. I've been unable to develop a query that will return cases of a single id sharing multiple numbers (and show the id and number in the report). I don't wish to delete these values via the query, I just need to see the values. See example below:
Here's a screenshot example: http://i591.photobucket.com/albums/ss355/riggins_83/table2_zps5509f3cf.jpg I appreciate the assistance, I've tried all the code posted here and it hasn't given me the output I'm looking for. As seen in the screenshot it's possible for the same ID number and Number to appear in the table multiple times with a different transaction number, what shouldn't occur is what's on rows 1 and 2 (two different numbers with same ID number). The ID number is a value that should always be tied to the same Number which the transaction is only linked to that line. I'm trying to generate output of each number that's sharing an ID number (and the shared ID Number if possible).
Test IDNumber Number Transaction
1 31 1551 5
2 31 1553 7
3 32 1701 8
4 33 1701 9
5 33 1701 10
6 33 1701 11
7 39 1885 12
The result of output I would need:
IDNumber Number
31 1551
31 1553
This output is showing me the Number (and ID number) in cases where an ID number is being shared between two (or possibly more) numbers. I know there are cases in the table where an ID number is being shared among many numbers.
Any assistance is greatly appreciated!
SELECT *
FROM thetable t0
WHERE EXISTS (
SELECT *
FROM thetable t1
WHERE t1.id = t0.id
-- Not clear from the question if the OP wants the records
-- to differ by number
-- AND t1.number <> t1.number
-- ... or by "transaction"
AND t1."transaction" <> t0."transaction"
-- ... or by either ???
-- AND (t1.number <> t1.number OR t1."transaction" <> t0."transaction")
);
SELECT IDNumber, Number
FROM YourTable
WHERE IDNumber IN (
SELECT IDNumber
FROM YourTable
GROUP BY IDNumber
HAVING COUNT(DISTINCT number) > 1
)
The subquery returns all the IDNumbers with more than 1 Number. Then the main query returns all the numbers for each of those IDNumbers.
DEMO
I have a SQL problem that I don't have the vocabulary to explain very well.
Here is a simplified table. My goal is to identify groups where the Tax_IDs are not equal. In this case, the query should return groups 1 and 3.
Group Line_ID Tax_ID
1 1001 11
1 1002 13
2 1003 17
2 1004 17
3 1005 23
3 1006 29
I can easily perform comparisons across rows, however I do not know how to perform comparisons "down" a table (here is really where my vocabulary fails me). I.e. what is the syntax that will cause SQL to compare Tax_ID values within groups?
Any help appreciated,
OB
The simplest way is to use group by with a having clause:
select "group"
from t
group by "group"
having min(tax_id) <> max(tax_id);
You can also phrase the having clause as:
having count(distinct tax_id) > 1;
However, count(distinct) is more expensive than just a min() or max()operation.
I have two identical tables as following:
Table 1
Student#|name|Course1#|Course2#|Course3#
456 abc 12 76 89
789 def 09 13 76
345 ghi 56 34 14
Table 2
Student#|name|Course1#|Course2#|Course3#
456 abc 12 76 89
789 def 90 13 76
345 ghi 56 34 14
Table1 will contain latest data and table 2 will keep a copy of table 1. Table 2 is updated everytime after updation of table 1 and I do not want a complete truncation and insertion. I want to fire a query which will compare these two tables and return only those rows in which value is changed. On the basis of these vale i can fire an update in table 2.
For eg: in table 1, student# 789 have a value changes for course 1# as 90 from 09, but table 2 still have old value. When I fire query i should get result like:
Student#|name|Course1#|Course2#|Course3#
789 def 90 13 76
It would rarely make sense to have two copies of the same data let alone try to keep two copies of data and periodically try to keep them in sync. So the premise seems rather suspect.
It sounds like you are looking for something like
UPDATE table2 t2
SET (course1, course2, course3) = (SELECT course1, course2, course3
FROM table1 t1
WHERE t1.student = t2.student)
WHERE EXISTS( SELECT 1
FROM table1 t1
WHERE t1.student = t2.student
AND ( t1.course1 != t2.course1
OR t1.course2 != t2.course2
OR t1.course3 != t2.course3) );
This won't account for cases where either table has a NULL value. If you want to replace a NULL value in table2 with a non-NULL value from table1 if it is available, and assuming -1 is not a valid value for that column, the predicate in the EXISTS clause would change to look something like t1.course1 != nvl(t2.course1, -1).
Create trigger on T1 for INSERT,DELETE,UPDATE ,in the trigger put the dirty KEYS/rows in onather table, then periodly check the dirty tracing table. Or in the trigger update T2 directlly.