replace missing value in update left join statement - sql

I updated an existing table with the update left join statement as per the following:
UPDATE A
SET A.SPSS_FieldForce = B.Remarks
FROM FBL1IN_working as A
left JOIN remarks_master_data as B
ON A.Vendor = B.Vendor_Code;
However, I need to replace the NULL values in the SPSS_FieldForce column with "Non SPSS / FFV' value. Currently, I am doing this with another statement as follows:
UPDATE
FBL1IN_working
SET
SPSS_FieldForce = 'Non SPSS/ FFV'
WHERE
SPSS_FieldForce IS NULL;
This does the job, but I would like to combine this two different statement into one. I am sure that there is a way to replace the missing value on the first update left join statement, but I just have no clue how to get it done.

It seems to be sqlserver syntax, right ?
Then
UPDATE A
SET A.SPSS_FieldForce = WHEN B.Vendor_Code IS NULL THEN 'Non SPSS / FFV' ELSE B.Remarks END
FROM FBL1IN_working as A
LEFT JOIN remarks_master_data as B ON A.Vendor = B.Vendor_Code;
Having B.Vendor_Code to be NULL means that the record is missing in your B table

Use COALESCE():
UPDATE w
SET SPSS_FieldForce = COALESCE(rmd.Remarks, 'Non SPSS/ FFV')
FROM FBL1IN_working w LEFT JOIN
remarks_master_data rmd
ON w.Vendor = rmd.Vendor_Code;
Notice that I also changed the table aliases so they are meaningful -- abbreviations for the table names. Arbitrary letters make the query much harder to read.

UPDATE A SET
A.SPSS_FieldForce = ISNULL( B.Remarks, 'Non SPSS/ FFV')
FROM FBL1IN_working as A
left JOIN remarks_master_data as B ON A.Vendor = B.Vendor_Code;

Related

Hive non-equi Join on OR condition

I have two tables I want to join on 3 keys. However, one of the keys may contain a value that doesn't exist in the other table, but I still want to retain these records upon query.
Something similar to this where key_3 in the first_table may contain a value of 0 which does not exist in the second_table.
SELECT
f.key_1,
f.key_2,
f.key_3,
s.column_4
FROM
first_table f
LEFT OUTER JOIN second_table s
ON f.key_1 = s.key_1
AND f.key_2 = s.key_2
AND (f.key_3 = s.key_3 OR f.key_3 = 0)
When I run this I get an error of OR not supported in JOIN currently '0'. I know in newer versions of Hive this is allowed, but is there a workaround for it in older versions.
Move condition with OR to the WHERE clause:
SELECT
f.key_1,
f.key_2,
f.key_3,
s.column_4
FROM
first_table f
LEFT OUTER JOIN second_table s
ON f.key_1 = s.key_1
AND f.key_2 = s.key_2
WHERE f.key_3 = s.key_3
OR f.key_3 = 0
OR s.key_1 is NULL --allow not joined records
I may not fully understand your question, but doesn't a simple left join do what you want?
SELECT f.key_1, f.key_2, f.key_3, s.column_4
FROM first_table f LEFT OUTER JOIN
second_table s
ON f.key_1 = s.key_1 AND
f.key_2 = s.key_2 AND
f.key_3 = s.key_3 ;
If there is no match in the second table -- regardless of the values in the first table -- the rows from the first table are still returned.

Why Hive SQL returning NULL values for a particular column in Select statement when that column has all double values?

I'm using Hive SQL. Version is Hive 1.1.0-cdh5.14.0. In my example below, sp.close is a column with type double values. I checked sp.column and there are definitely no NULL values. Yet, in this select statement below, sp.close shows all NULL values. Why?
select
step1.*,
sp.close
from
step1 left join stockprices2 sp on (
step1.symbol = sp.symbol and
step1.year = sp.year and
step1.startmonth = sp.month and
step1.startday = sp.day and
step1.sector = sp.sector
)
;
Most likely, your left join did not find a matchin row in stockprices2. In that event, the row from step1 is retained, but all columns from stockprices2 will be null in the resultset. This is by design how the database signals that the left join came up empty.
You can easily verify that by just chaning the left join to an inner join: you should have less rows returned (where there is no match in stockprices2, the row from step1 is removed from the resultset), and no null values in sp.close.
Or you can add one of the columns used in the left join conditions in the select clause, and see that it's null too.
select
st.*,
sp.close,
sp.symbol -- null too
from step1 st
left join stockprices2 sp
on st.symbol = sp.symbol
and st.year = sp.year
and st.startmonth = sp.month
and st.startday = sp.day
and st.sector = sp.sector
Side note: the parentheses around the join conditions are superfluous.

ORA-00933: SQL command not properly ended with INSERT INTO...SELECT statement

I fix my problem by chance, but I really want to know why it works :),
Here's the thing:
I get the ORA-00933: SQL command not properly ended Error when I execute the following SQL statement:
INSERT INTO BASP_DX.QLR#GT(BDCDYH, QSZT)
SELECT NVL(e.BDCDYH, ' '),b.LIFECYCLE AS QSZT
FROM DJ_DY a
LEFT JOIN DJ_XGDJGL d
ON d.ZSLBH = a.SLBH
LEFT JOIN DJ_DJB e
ON e.SLBH = d.FSLBH
AND e.SLBH = '0123456789'
LEFT JOIN DJ_QLRGL f
ON f.SLBH = e.SLBH
AND f.QLRLX = 'Person1'
LEFT JOIN DJ_QLRGL b
ON b.SLBH = a.SLBH
AND (b.QLRLX = 'Person2' OR (b.QLRLX = 'Person3' AND b.QLRID = f.QLRID))
WHERE a.SLBH = '12345'
AND e.SLBH IS NOT NULL
-- add the condition to ensure that
-- this statement and the second statement get the same result
AND b.QLRID IS NOT NULL
AND (a.LIFECYCLE = '0' OR a.LIFECYCLE IS NULL);
I remove all the unnecessary insert value, related table and condition from the original SQL statement, to focus on the problem part.
Then I google it, from this post I know the causes may be:
An INSERT statement with an ORDER BY clause or an INNER JOIN
A DELETE statement with an INNER JOIN or ORDER BY clause
An UPDATE statement with an INNER JOIN
Apparently, these are not my type. I didn't use the INNER JOIN and ORDER BY, all I use is LEFT JOIN statement, so I wonder it might be reason that I set too many conditions with the LEFT JOIN statement (such as LEFT JOIN DJ_QLRGL b), so I try move the conditions after WHERE clause, it looks like this:
INSERT INTO BASP_DX.QLR#GT(BDCDYH, QSZT)
SELECT NVL(e.BDCDYH, ' '),b.LIFECYCLE AS QSZT
FROM DJ_DY a
LEFT JOIN DJ_XGDJGL d
ON d.ZSLBH = a.SLBH
LEFT JOIN DJ_DJB e
ON e.SLBH = d.FSLBH
AND e.SLBH = '0123456789'
LEFT JOIN DJ_QLRGL f
ON f.SLBH = e.SLBH
AND f.QLRLX = 'Person1'
LEFT JOIN DJ_QLRGL b
ON b.SLBH = a.SLBH
-- this conditions move to WHERE clause
WHERE a.SLBH = '12345'
AND e.SLBH IS NOT NULL
-- here is the original LEFT JOIN condition
AND (b.QLRLX = 'Person2' OR (b.QLRLX = 'Person3' AND b.QLRID = f.QLRID))
AND (a.LIFECYCLE = '0' OR a.LIFECYCLE IS NULL);
Then it works!
But why?
I just want to know the reason for this situation.
Solution
the problem is triangular join, the LEFT JOIN conditions can't contain the condition concerning both the self join table, in this case, it's b.QLRID = f.QLRID, so when I remove the b.QLRID = f.QLRID condition, it works.
Firstly, the join of "DJ_QLRGL b" is not LEFT any more,
as WHERE condition excludes rows with no b counterpart found

Oracle left outer join, only want the null values

I'm working on a problem with two tables. Charge and ChargeHistory. I want to display a selection of columns from both tables where either the matching row in ChargeHistory has a different value and/or date from Charge or if there is no matching entry in ChargeHistory at all.
I'm using a left outer join declared using the ansi standard and while it does show the rows correctly where there is a difference, it isn't showing the null entries.
I've read that there can sometimes be issues if you are using the WHERE clause as well as the ON clause. However when I try and put all the conditons in the ON clause the query takes too long > 15 minutes (so long I have just cancelled the runs).
To make things worse both tables use a three part compound key.
Does anyone have any ideas as to why the null values are being left out?
SELECT values...
FROM bcharge charge
LEFT OUTER JOIN chgHist history
ON charge.key1 = history.key1 AND charge.key2 = history.key2 AND charge.key3 = history.key3 AND charge.chargeType = history.chargeType
WHERE charge.chargeType = '2'
AND (charge.value <> history.value OR charge.date <> history.date)
ORDER BY key1, key2, key
You probably want to explicitly select the null values:
SELECT values...
FROM bcharge charge
LEFT OUTER JOIN chgHist history
ON charge.key1 = history.key1 AND charge.key2 = history.key2 AND charge.key3 = history.key3 AND charge.chargeType = history.chargeType
WHERE charge.chargeType = '2'
AND ((charge.value <> history.value or history.value is null) OR (charge.date <> history.date or history.date is null))
ORDER BY key1, key2, key
You can explicitly look for a match in the where. I would recommend looking at one of the keys used for the join:
SELECT . . .
FROM bcharge charge LEFT OUTER JOIN
chgHist history
ON charge.key1 = history.key1 AND charge.key2 = history.key2 AND
charge.key3 = history.key3 AND charge.chargeType = history.chargeType
WHERE charge.chargeType = '2' AND
(charge.value <> history.value OR charge.date <> history.date OR history.key1 is null)
ORDER BY key1, key2, key;
The expressions charge.value <> history.value change the left outer join to an inner join because NULL results will be filtered out.
A WHERE clause filters the data returned by a join. Therefore when your inner table has null data for a particular column, the corresponding rows get filtered out based on your specified condition. That is why you should move that logic to the ON clause instead.
For the performance issues, you could consider adding indexes on the columns used for joining and filtering.
Have a look at this site, it will be very helpful for you, visual illustration of all the join statements with code samples
blog.codinghorror.com
Quoted of the relevant info in the above link:
SELECT * FROM TableA
LEFT OUTER JOIN TableB
ON TableA.name = TableB.name
Sample output:
id name id name
-- ---- -- ----
1 Pirate 2 Pirate
2 Monkey null null
3 Ninja 4 Ninja
4 Spaghetti null null
Left outer join
produces a complete set of records from Table A, with the matching records (where available) in Table B. If there is no match, the right side will contain null
For any field from an outer joined table used in the where clause you must also permit an IS NULL option for that same field, otherwise you negate the effect of the outer join and the result is the same as if you had used an inner join.
SELECT
*
FROM bcharge charge
LEFT OUTER JOIN chgHist history
ON charge.key1 = history.key1
AND charge.key2 = history.key2
AND charge.key3 = history.key3
AND charge.chargeType = history.chargeType
WHERE charge.chargeType = '2'
AND (
(charge.value <> history.value OR history.value IS NULL)
OR
(charge.date <> history.date OR history.date IS NULL)
)
ORDER BY
key1, key2, key3
Edit: Appears that this is the same query structure used by Rene above, so treat this one as in support of that please.

How to UPDATE only the columns that have NOT been previously updated in SQL SERVER

Pardon the title as I didn't know how to put it up in title.
I have a table staging_cust_acct (naics_cd, naics_desc varchar, is_pep, phone_num, is_updated, update_date)
I wrote below statements to update this table. I need to use the code to update only those columns which have NOT been previously updated (for which I have the is_updated (0 or 1) and update_date columns)
In case you are wondering why I made separate update statements, it is because there are many more update statements which have dependencies (like UPDATE 2 statement needs to be run after UPDATE 1 only)
What can I add in below SQL statements to apply the above mentioned logic?
-- Update NAIC code and description
UPDATE S
SET s.naics_cd = left(n.naic, 6),
s.naics_desc = substring(n.naic, 9, 255)
from mtb..staging_cust_acct s
right outer join mtb_aml..tb_party_kyc e
on e.customerinternalid = s.party_key
right outer join mtb_aml..tb_ref_naic n
on e.d_case_id = n.d_case_id
-- Update is_PEP Flag
UPDATE S
SET s.is_pep = '1'
from mtb..staging_cust_acct s
right outer join mtb_aml..tb_party_kyc e
on e.CustomerInternalID = s.party_key
right outer join mtb_aml..tb_ref_pep_details p
on e.d_case_id = p.d_case_id
-- Update party phone number
UPDATE S
SET s.phone_num = pc.phone
from mtb..staging_cust_acct s
right outer join mtb_aml..tb_party_kyc e
on s.party_key = e.customerinternalid
right outer join mtb_aml..tb_ref_primary_contact pc
on pc.d_case_id = e.d_case_id
Add where condition in sql to check is_updated (0 or 1) and update_date like:
UPDATE S
SET s.naics_cd = left(n.naic, 6),
s.naics_desc = substring(n.naic, 9, 255)
from mtb..staging_cust_acct s
right outer join mtb_aml..tb_party_kyc e
on e.customerinternalid = s.party_key
right outer join mtb_aml..tb_ref_naic n
on e.d_case_id = n.d_case_id
WHERE s.is_updated=0 --Added Condition
AND s.update_date IS NULL --Added Condition
Here, I am assuming is_updated=0 means not updated and update_date is nullable & set only when value is edited.
If above assumption is not good for you, you can change where condition accordingly.