SQL null values inner join - sql

I would like to only include a comparison on an inner join if the value is not null. E.g. I am comparing addresses some addresses have the same house number street address and tag but have a distinct apartment number, but other addresses don't have apartment numbers associated with them so the value is null. These values don't get joined.
A left outer join won't work because I need to join data associated with the values that have null apartment values. Any ideas?
select * from address a
inner join ma_address ma
on a.number=ma.number
and a.street=ma.street
and a.tag=ma.tag
and a.apt=ma.apt
Thanks,

This is because in SQL, NULL does not equal NULL. Try something like this for each join criteria
(a.<col> = ma.<col> OR (a.<col> IS NULL AND ma.<col> IS NULL))

A value of NULL indicates that the value is unknown. A value of NULL is different from an empty or zero value. No two null values are equal. Comparisons between two null values, or between a NULL and any other value, return unknown because the value of each NULL is unknown.
Null values generally indicate data that is unknown, not applicable, or that the data will be added later. For example, a customer's middle initial may not be known at the time the customer places an order.
Following is information about nulls:
1. To test for null values in a query, use IS NULL or IS NOT NULL in the WHERE clause.
2. When query results are viewed in SQL Server Management Studio Code editor, null values are shown as NULL in the result set.
3. Null values can be inserted into a column by explicitly stating NULL in an INSERT or UPDATE statement, by leaving a column out of an INSERT statement, or when adding a new column to an existing table by using the ALTER TABLE statement.
4. Null values cannot be used for information that is required to distinguish one row in a table from another row in a table, such as primary keys.
Source: http://technet.microsoft.com/en-us/library/ms191504(v=sql.105).aspx

Related

Join 2 tables by 1 field, partial matching on other two fields - no cartesian product

I have 2 tables, representing the substitutions of components in an intervention (ID_TK), each with a Part Number OLD and a Part Number NEW, from two different systems point of view (PN OLD and NEW in one system, HWC OLD and NEW in the other one).
The number of rows in the two tables may be different for each ID_TK.
ID_SOST is the unique KEY in the first table, PR_ID is the unique key in the second one.
However, only the id intervention (ID_TK) links the two tables exactly.
I have to check if the substitutions match in the two tables for each intervention.
"Match" means: same ID_TK, AND PN_OLD must be substring (or equal) to HWC_OLD, AND PN_NEW must be substring (or equal) to HWC_NEW (both uppercase):
case
when
(UPPER(PN_NEW) = UPPER(SUBSTR(HWC_NEW,1,LENGTH(PN_NEW))) AND UPPER(PN_OLD) = UPPER(SUBSTR(HWC_OLD,1,LENGTH(PN_OLD)))) THEN 'YES' else 'NO' as MATCH
In the desiderata result table, the "matching" couples ID_SOST-PR_ID have to be listed first, and they have not been considered for any other matching in the ID_TK (the best option is the exact match); the remaining non-matching couples have to be listed after the matching ones, first listing the better similarity. The difficulty is that I don't want to show the cartesian product of the non-matching substitutions(PRs and ID_SOSTs). BTW, if the number of PR (or SOST) is different, null will fill the missing fields.
So first, for future reference, here's how to give example data in a question:
create table table1 (id_tk varchar2(20), id_sost varchar2(20), hwc_old varchar2(20), hwc_new varchar2(20));
create table table2 (id_tk varchar2(20), pr_id varchar2(20), pn_old varchar2(20), pn_new varchar2(20));
insert into table1 values ('TK0000001296676', '00000000199412', '3AL80407AA', '3AL80407AA');
insert into table1 values ('TK0000001296676', '00000000199413', '3AL79090BAAS', '3AL79090BAAS');
insert into table2 values ('TK0000001296676', 'pr-20191025-008', '3AL79090BAAS04', '3AL79090BA');
insert into table2 values ('TK0000001296676', 'pr-20191115-009', '3AL79090BA', '3AL79090BA');
insert into table2 values ('TK0000001296676', 'pr-20191115-011', '3AL79090BAAS04', '3AL79090BA');
It's very helpful - please don't make us re-type text that you already have. Just copy/pasting the data from Excel is fine too.
For the actual query - we're doing a full outer join, and only including the rows which either match, or have nulls instead of a match. We could also have written this as a full outer join, excluding the cartesian product rows which don't match.
select nvl(table1.id_tk, table2.id_tk) as id_tk, id_sost, hwc_old, hwc_new, pr_id, pn_old, pn_new,
case when (UPPER(PN_NEW) = UPPER(SUBSTR(HWC_NEW,1,LENGTH(PN_NEW))) AND UPPER(PN_OLD) = UPPER(SUBSTR(HWC_OLD,1,LENGTH(PN_OLD)))) THEN 'YES' else 'NO' end as MATCH
from table1
full outer join table2
on (table1.id_tk = table2.id_tk -- display matches if they exist
and UPPER(PN_NEW) = UPPER(SUBSTR(HWC_NEW,1,LENGTH(PN_NEW)))
and UPPER(PN_OLD) = UPPER(SUBSTR(HWC_OLD,1,LENGTH(PN_OLD)))
) OR ( -- also include rows with no matches
(id_sost is null or pr_id is null))
order by MATCH desc -- show matches first
;
Output - my output is a little different from yours, because I don't think you really want to have non-matching ID_SOST - PR_ID data in the same row. It's hard to do in SQL, and I think this way is more clear that the table1/table2 data in the row is not a match with each other.
ID_TK ID_SOST HWC_OLD HWC_NEW PR_ID PN_OLD PN_NEW MATCH
TK0000001296676 199413 3AL79090BAAS 3AL79090BAAS pr-20191115-009 3AL79090BA 3AL79090BA YES
TK0000001296676 null null null pr-20191115-011 3AL79090BAAS04 3AL79090BA NO
TK0000001296676 null null null pr-20191025-008 3AL79090BAAS04 3AL79090BA NO
TK0000001296676 199412 3AL80407AA 3AL80407AA null null null NO

SQL Server looking for missing records in one table where column may contain NULL

I have two databases Live and Dev. The Dev database contains a number of records which need to be added to the live database, but the two databases share a number of records. There is a unique key on MainspecialityCode, AppointmentType and ConsultantCode. No record exists with all three being null but records exist where AppointmentType and Consultantcode
I tried the following:
SELECT [R_Dev].[ID]
,[R_Dev].[MainspecialityCode]
,[R_Dev].[Consultantcode]
,[R_Dev].[AppointmentType]
,[R_Dev].[GPCode]
,[R_Dev].[Process]
,[R_Dev].[Routing]
,[R_Dev].[CernerDocumentName]
,[R_Dev].[EmailAlert]
,[R_Dev].[ShowConsultant]
,[R_LIV].[MainspecialityCode]
,[R_LIV].[Consultantcode]
,[R_LIV].[AppointmentType]
FROM
[STG1DOCDB10].[CalypsoPrint_Live].[dbo].[Cerner_Routing] R_Dev
LEFT JOIN
[CalypsoPrint_Live].[dbo].[Cerner_Routing] R_LIV ON [R_LIV].[MainspecialityCode] = [R_Dev].[MainspecialityCode]
AND [R_LIV].[Consultantcode] = [R_Dev].[Consultantcode]
AND [R_LIV].[AppointmentType] = [R_Dev].AppointmentType
WHERE
[R_LIV].[MainspecialityCode] IS NULL
AND [R_LIV].[Consultantcode] IS NULL
AND [R_LIV].[AppointmentType] IS NULL
However I am finding that records which are in both still appear in the results. So how can I do the comparison in the Where clause which only lists the records in dev that are not in live.
The problem are your NULL values which are failing the LEFT JOIN. So, modify that to take them into account:
FROM [STG1DOCDB10].[CalypsoPrint_Live].[dbo].[Cerner_Routing] R_Dev LEFT JOIN
[CalypsoPrint_Live].[dbo].[Cerner_Routing] R_LIV
ON [R_LIV].[MainspecialityCode] = [R_Dev].[MainspecialityCode] And
([R_LIV].[Consultantcode] = [R_Dev].[Consultantcode] OR
[R_LIV].[Consultantcode] IS NULL AND [R_Dev].[Consultantcode] IS NULL
) AND
([R_LIV].[AppointmentType] = [R_Dev].AppointmentType OR
[R_LIV].[AppointmentType] IS NULL AND [R_Dev].AppointmentType IS NULL
)
Your WHERE clause only needs to check for MainspecialityCode.

Need to select all the Null value records and email them back to the sender but batch upload the rest of the correctly filled resords

If i have a table that on occasion has columns account, dim1,dim2,description,aparid with Null values, but the other records with correctly filled data.
How do I go about extracting these fields with Null values but upload the rest of the data into a batch input system.
SQL query below returns two results:
First - with rows where are no Null values;
Second - rows having at least one Null value;
-- Table variable to store KeyIds
DECLARE #KeyTbl table(KeyID bigint)
-- Collecting KeyId's of rows where is no Null values
INSERT INTO #KeyTbl
SELECT batch_id FROM Test
WHERE account IS NOT NULL
AND dim_1 is not NULL
AND dim_2 is not NULL
AND description IS NOT NULL
AND apar_id IS NOT NULL;
-- All rows where are no Null values
SELECT Test.* FROM #KeyTbl Keys
INNER JOIN Test
ON Test.batch_id = Keys.KeyID;
-- Rows having Null values
SELECT Test.* FROM #KeyTbl Keys
RIGHT JOIN Test
ON Test.batch_id = Keys.KeyID
WHERE Keys.KeyID IS NULL;
SqlFiddle

How to assign default value to empty column

I am working on report builder 6i.
I have two tables
1- Company_info
2- Address_info
Comp_addr_code is a foreign key in company_info table which is primary key in
Address_info table.Now I am retrieving data from address_table base on comp_address_Code.But in some cases first three columns are empty in Address_info table.
I want for these columns 'X' should be displayed.What Changes should I make in my SQL Statement.My Sql statement is:
SELECT COMP_CODE, COMP_NAME, COMP_ADDR_CODE,
FROM COMPANY_INFO, ADDRESS_INFO
WHERE COMP_CODE=:P_COMP_CODE
AND COMP_ADDR_CODE=ADDR_CODE
Use COALESCE, it picks the first non-null value. I.e. if the column value is not null, return the column value, else return specified default value:
select coalesce(COMP_CODE,'X'),
coalesce(COMP_NAME,'X'),
etc
As given, only COMP_NAME can be NULL; if COMP_CODE or COMP_ADDR_CODE are null, those rows will not be in the resultset.
NVL or COALESCE are usually used to replace null values with other values, e.g.
SELECT
COMP_CODE,
nvl(COMP_NAME, 'X')
COMP_ADDR_CODE
FROM COMPANY_INFO,ADDRESS_INFO
WHERE COMP_CODE=:P_COMP_CODE
AND
COMP_ADDR_CODE=ADDR_CODE

How to delete a row in SQL based on a NULL condition

I just started learning SQL; I've created a table. Learned insert command and inserted values in 2 rows. However I've inserted null values in 3rd.
Now I want to delete the third row which has 2 columns with no values in it.
I'm using the following query:
delete employee where city=null;
It doesn't seem to be working!
According SQL 92 standard many logical operations with null values like
> null
= null
and null
or null
not null
should always return null (and never true). Some DBMS (e.g. Oracle) follow this rule rigorously, some (MS SQL) can have a mode that null = null returns true, not required null. In order to be compartible with SQL 92 and so with (almost) all DBMSs, you should use is null or is not null standard comparisons, in your case
delete from employee
where city is null -- <- Standard comparison
You need the is null "operator":
delete from employee where city is null;
This is because in SQL, nothing is equal to NULL.
You can't use = with NULL. Instead, use:
delete employee where city is null;
To achieve this
you will have to write this query
DELETE from table_name WHERE city IS NULL;
this query will delete the rows/records WHERE city is null
Here you know you have added Null in city column so checking with is null will work but it's also possible to add an empty string in city column. So if your business condition is like delete all records from employee table where city is either null or empty i.e. with no values you should write as:
delete from employee where isnull(city,'')='';
change it :
delete from table_name where city is null
or
delete from table_name where city = null