I am using Oracle DB.
I have a static query like
SELECT * FROM TESTSCHEMA.TABLE_A WHERE LOAN_ID = :LOAN_ID
The remaining where condition is coming from a table .
Now we came across a scenario where we need to introduce a new table if one column in TABLE_A is NULL i need to take value from TABLE_B
We are not looking for a code change or deployment , instead if we can update in table .
SELECT
*
FROM
TESTSCHEMA.TABLE_A
WHERE
LOAN_ID = :LOAN_ID
AND
(
/* if COLUMNA is NULL in TABLE_A
then i need to pull value from TABLE_B in the same select statement */
)
My interpretation...
If you're wanting to limit the data returned based on columnA when it has a value, but when it doesn't have a value (NULL) use columnB from table B... to limit by it; then coalesce & a sub query should do it.
Or you could replace the whole subquery with a scalar function and call it.
SELECT *
FROM TESTSCHEMA.TABLE_A
WHERE LOAN_ID = :LOAN_ID
AND COALESCE(COLUMNA,(SELECT ColumNName
FROM table_B
WHERE [Some Limits to get 1 record always]) = DesiredValue
Replace ColumnName with desired column from table_B
Replace DesiredValue with value you want to compare columnA, or ColumnB to.
Add Where clause limits to table_B to ensure you only get 1 record back always.
Or...
SELECT *
FROM TESTSCHEMA.TABLE_A
WHERE LOAN_ID = :LOAN_ID
AND COALESCE(COLUMNA,GetBValueWhenAValueNull(Paramaters?)) = DesiredValue
But as that would require a deployment/code change... guessing not
What you can do is remove the NULL values from tableA
UPDATE TABLE_A
SET value = (SELECT TABLE_B.value
FROM TABLE_B
WHERE TABLE_A.LOAN_ID = TABLE_B.LOAN_ID )
WHERE LOAN_ID = :LOAN_ID
AND value is NULL
Related
In Snowflake I am trying to insert updated records to a table. Then I want to identify the records that were just inserted as the most recent records save that as the final table output in a new column called ACTIVE which will either be true or flase. I am having an issue incorporating some sort of updated table segment to my current query. I need everything be contained in the same query rather than break it up into separate parts.
I have my table as follows
CREATE TABLE IF NOT EXISTS MY_TABLE
(
LINK_ID BINARY NOT NULL,
LOAD TIMESTAMP NOT NULL,
SOURCE STRING NOT NULL,
SOURCE_DATE TIMESTAMP NOT NULL,
ORDER BIGINT NOT NULL,
ID BINARY NOT NULL,
ATTRIBUTE_ID BINARY NOT NULL
);
I have records being inserted in this way:
INSERT ALL
WHEN HAS_DATA AND ID_SEQ_NUM > 1 AND (SELECT COUNT(1) FROM MY_TABLE WHERE ID = KEY) = 0 THEN
INTO MY_TABLE VALUES (
LINK_KEY,
TIME,
DATASET_NAME,
DATASET_DATE,
ORDER_NUMBER,
O_KEY,
OA_KEY
)
SELECT *
FROM TEST_TABLE;
I would like my final table from this to be the output as
SELECT *, ORDER != MAX(ORDER) OVER (PARTITION BY ID) AS ACTIVE
FROM MY_TABLE;
This is so I can identify the most recent record per ID group as ACTIVE/TRUE and the previous records within that ID group as INACTIVE/FALSE
I tried to use an insert overwrite method like this
INSERT ALL
WHEN HAS_DATA AND ID_SEQ_NUM > 1 AND (SELECT COUNT(1) FROM MY_TABLE WHERE ID = KEY) = 0 THEN
INTO MY_TABLE VALUES (
LINK_KEY,
TIME,
DATASET_NAME,
DATASET_DATE,
ORDER_NUMBER,
O_KEY,
OA_KEY
)
INSERT OVERWRITE INTO MY_TABLE
SELECT *, RSRC_OFFSET != MAX(RSRC_OFFSET) OVER (PARTITION BY ID) AS ACTIVE
FROM L_OPTION_OPTION_ALLOCATION_TEST
SELECT *
FROM MY_TABLE;
However, it seems the insert overwrite doesn't work in this way (also I am not sure if I can just add a new column to the table like this?). Is there a way I can incorporate it into this query or a different way to update the table with this new ACTIVE column within this query itself?
Also I am using INSERT ALL here because I actually have multiple different tables I am inserting into at once, but this is the current table that I am trying to modify.
You can use the overwrite option with conditional multi-table inserts.
Starting with your current statement:
INSERT ALL
WHEN HAS_DATA AND ID_SEQ_NUM > 1 AND (SELECT COUNT(1) FROM MY_TABLE WHERE ID = KEY) = 0 THEN
INTO MY_TABLE VALUES (
LINK_KEY,
TIME,
DATASET_NAME,
DATASET_DATE,
ORDER_NUMBER,
O_KEY,
OA_KEY
)
SELECT *
FROM TEST_TABLE;
Add the overwrite option immediately after the insert command:
INSERT OVERWRITE ALL
WHEN HAS_DATA AND ID_SEQ_NUM > 1 AND (SELECT COUNT(1) FROM MY_TABLE WHERE ID = KEY) = 0 THEN
INTO MY_TABLE VALUES (
LINK_KEY,
TIME,
DATASET_NAME,
DATASET_DATE,
ORDER_NUMBER,
O_KEY,
OA_KEY
)
SELECT *
FROM TEST_TABLE;
Note that this will truncate and insert ALL tables in the multi-table insert. There is not a way to be selective about which tables get truncated and inserted and which don't.
https://docs.snowflake.com/en/sql-reference/sql/insert-multi-table.html#optional-parameters
I am trying to perform a merge to insert and update as the case may be in a table. However in table 1, I only want it to insert the unique values of the tbl2.rfc field regardless if my other fields change, I only want to show the unique values of said field. I am occupying the ROW_NUMBER function to bring only unique values, but I have not been able to add this function to my merge.
MERGE INTO B69_TBL1 tbl1
USING (SELECT T1.*, ROW_NUMBER() OVER (PARTITION BY T1.rfc ORDER BY T1.rfc DESC) ENUMERADO
FROM B69_TBL2 tbl2
WHEN MATCHED THEN
UPDATE SET
tbl1.id_tbl1 = tbl2.id_con,
tbl1.rfc = tbl2.rfc,
tbl1.rfc = tbl2.name_cont
WHEN NOT MATCHED THEN
INSERT (tbl1.id_tbl1,tbl1.tbl1tipo,tbl1.id_concentrado,tbl1.rfc,
tbl1.name_cont,tbl1.baja_logica,tbl1.last_update)
VALUES (id_tbl1autt.nextval,'1','1',tbl2.id_concentrado,tbl2.rfc,
tbl2.name_cont,'0', '11/05/2021')
) T1
WHERE ENUMERADO=1
AND RFC IS NOT NULL
The error it marks is 00907. 00000 - "missing right parenthesis"
because I had it like this and it fails precisely in the on.
MERGE INTO B69_TBL1 tbl1
USING (SELECT T1.*, ROW_NUMBER() OVER (PARTITION BY T1.rfc ORDER BY T1.rfc DESC) ENUMERADO
ON tbl1.rfc = tbl2.rfc
FROM B69_TBL2 tbl2 )
WHEN MATCHED THEN
UPDATE SET
tbl1.id_alert = tbl2.id_con,
tbl1.rfc = tbl2.rfc,
tbl1.rfc = tbl2.name_cont
WHEN NOT MATCHED THEN
INSERT (tbl1.id_alert,tbl1.alertype,tbl1.id_con,tbl1.rfc,
tbl1.name_cont,tbl1.baja_logica,tbl1.last_update)
VALUES (id_tbl1autt.nextval,'1','1',tbl2.id_con,tbl2.rfc,
tbl2.name_cont,'0', '11/05/2021')
) T1
WHERE ENUMERADO=1
AND RFC IS NOT NULL
Your ON clause is in the wrong place;
You had the tbl2 alias inside the USING query instead of following it;
You do not need the tbl1 aliases before the destination column names in the UPDATE or INSERT;
You are updating the rfc column twice (I removed the second instance);
There was a strange T1 alias after the insert that should be inside the USING query; and
You can use a DATE literal rather than a string.
There may be other errors, as I do not have your tables to test the query.
MERGE INTO B69_TBL1 tbl1
USING (
SELECT T1.*,
ROW_NUMBER() OVER (PARTITION BY T1.rfc ORDER BY T1.rfc DESC) AS ENUMERADO
FROM B69_TBL2 t1
) tbl2
ON tbl1.rfc = tbl2.rfc
WHEN MATCHED THEN
UPDATE SET
id_alert = tbl2.id_con,
rfc = tbl2.rfc
WHEN NOT MATCHED THEN
INSERT (
id_alert,
alertype,
id_con,
rfc,
name_cont,
baja_logica,
last_update
) VALUES (
id_tbl1autt.nextval,
'1',
'1',
tbl2.id_con,
tbl2.rfc,
tbl2.name_cont,
'0',
DATE '2021-05-11'
)
WHERE ENUMERADO=1
AND RFC IS NOT NULL
The Table_B contains duplicate records as seen below. What I am trying to do is lookup Table_A using Table_B.SERIAL_NUM and update Table_A .COVERAGE_END coloumn with the most recent Date value in COVERAGE_TO coloumn in Table_B.
Table_B
SERIAL_NUM ,COVERAGE_FROM ,COVERAGE_TO
123456 ,26/12/2014 ,13/12/2015
123456 ,14/12/2015 ,13/12/2016
23456 ,18/12/2014 ,13/12/2015
23456 ,14/12/2015 ,13/12/2016
Following is the update statement I am using.
update Table_A J
set ( J.COVERAGE_END_DATE)
=(select COVERAGE_TO from
(
select SERIAL_NUM, COVERAGE_TO, row_number() over(partition by SERIAL_NUM order by COVERAGE_TO desc) as rn from TABLE_B B
)where rn = 1
)
where exists
(
select * from TABLE_B Q where Q.SERIAL_NUM = J.SERIAL_NUMBER
)
;
However I get the following error
ORA-01427: single-row subquery returns more than one row
Can Some one please help me with this Query?
You have to compare J's SERIAL_NUMBER with B's to get the only proper value.
where rn = 1 and J.SERIAL_NUMBER = SERIAL_NUM
If not, subquery will return max values for every SERIAL_NUM.
I'm not sure why partitioning is needed here.
Would a simple MAX() not produce the needed result?
update table_a
set coverage_end_date = (
select max(coverage_to)
from table_b b inner join table_a a on b.serial_num = a.serial_num
)
;
I have found the following way for removing duplicates:
DELETE FROM
table_name A
WHERE
a.rowid >
ANY (
SELECT
B.rowid
FROM
table_name B
WHERE
A.col1 = B.col1
AND
A.col2 = B.col2
);
Could someone explain me step by step how does the query works?
TIA!
In Oracle, ROWID is a pseudo column points to the physical location of a row. The query does a self join and fetches those rows which have the same value of column 1 & column 2 - with the assumption that these keys are enough to identify as duplicate row.
Once the rows are fetched, the query then deletes those rowids which are larger than the first row fetched, thereby deleting duplicates
Like this:
DELETE FROM // The command to delete
table_name A //the table in which you want to remove duplicate
WHERE //condition
a.rowid > //checking the rowid which oracle adds to each row. Oracle Database rowid values contain information necessary to locate a row.
ANY ( //any row which has a condition
SELECT //select
B.rowid //rowid
FROM //from
table_name B //table name with alias name as B. Is used for making a self join
WHERE //condition
A.col1 = B.col1 //where the column1 has the same rowid
AND //and
A.col2 = B.col2 //where the column2 has the same rowid
);
I am trying to update columnA in tableA. The new values of ColumnA is extracted from tableB ColumnB, using column a as the ID. I am using the following queries, but i am unable to update the table.
update tableA a set columnA = (select b.columnB from tableb b where b.columnC = a.columnA)
where exists (select * from tableb b where b.columnC = a.columnA) and a.columnD = 'ABC'
For the above query i am getting the exception 'Single Row subquery returns more than one row'
update tableA a set a.columnA = b.columnB from tableb b on a.columnA = b.columnC where a.columnD = 'ABC'
For the above query i am getting the exception 'SQL command not properly ended'
update a set a.columnA = b.columnB from tablea a inner join tableb b on a.columnA=b.columnC where a.columnD = 'ABC'
For the above query i am getting the exception 'SQL command not properly ended'
I think your issue is that you have multiple rows in tableB that match ("where b.columnC = a.columnA"). So when you tell Oracle to:
set columnA = (
select b.columnB
from tableb b
where b.columnC = a.columnA)
where exists ...
its finding multiple rows in tableB for a given key value. You'll have to decide how you'd like Oracle to choose just one. For example, if you really don't care which of the multiple values, you could do something like (untested):
set columnA = (
select distinct(max(b.columnB))
from tableb b
where b.columnC = a.columnA)
where exists ...