SQL find difference between two table - sql

I need to compare email record (by email address) between two tables (Table A as Production data and B as old data) to find the difference and show the result in column such as "New", "Delete" and etc.
If exists in Table A, not in Table B, it should mark "New"
else if exists in Table B, not in Table A, it should mark "Delete"
if appears in both table, it should mark "Maintain"
I want the result like that
DisplayName LastName Diremail Result
==============================================
XXX XXX a#a.com New
ABC ABC 1#a.com Delete
DDD DDD 2#a.com Maintain
My code as follows:
SELECT b.DisplayName,
b.LastName,
b.diremail,
Result = CASE WHEN a.DirEmail IS NULL THEN 'New'
when b.DirEmail IS null then 'delete'
else 'Maintain'
END
FROM vHRIS_StaffDB b
LEFT JOIN HRIS_DL_Lists a
ON a.DirEmail = b.DirEmail
WHERE (
a.DirEmail IS NULL
OR a.DisplayName != b.DisplayName
)
but the data not correct as the code not return record which should "Delete"
(found in table b, not in table a)
pls advise. Thanks.

Sounds like you need full join instead of left join. Try this:
SELECT coalesce(b.DisplayName, a.DisplayName) DisplayName,
coalesce(b.LastName, a.LastName) LastName,
coalesce(b.diremail, a.diremail) diremail,
Result = CASE WHEN a.DirEmail IS NULL THEN 'New'
when b.DirEmail IS null then 'delete'
else 'Maintain'
END
FROM vHRIS_StaffDB b
FULL JOIN HRIS_DL_Lists a
ON a.DirEmail = b.DirEmail
WHERE (
a.DirEmail IS NULL
OR a.DisplayName != b.DisplayName
)

Related

JOIN AND CASE MORE AN TABLE

I have 2 tables; the first one ORG contains the following columns:
ORG_REF, ARB_REF, NAME, LEVEL, START_DATE
and the second one WORK contains these columns:
ARB_REF, WORK_STREET - WORK_NUM, WORK_ZIP
I want to do the following: write a select query that search in work and see if the WORK_STREET, WORK_ZIP are duplicate together, then you should look at WORK_NUM. If it is the same then output value ' ok ', but if WORK_NUM is not the same, output 'not ok'
I wrote this SQL query:
select
A.ARB_REF, A.WORK_STREET, A.WORK_NUM, A.WORK_ZIP
case when B.B = 1 then 'OK' else 'not ok' end
from
work A
join
(select
WORK_STREET, WORK_ZIP count(distinct , A.WORK_NUM) B
from
WORK
group by
WORK_STREET, WORK_ZIP) B on B.WORK_STREET = A.WORK_STREET
and B.WORK_ZIP = A.WORK_ZIP
Now I want to join the table ORG with this result I want to check if every address belong to org if it belong I should create a new column result and set it to yes in it (RESULT) AND show the "name" column otherwise set no in 'RESULT'.
Can anyone help me please?
While you can accomplish your result by adding a left outer join to the query you've already started, it might be easiest to just use count() over....
with org_data as (
-- do the inner join before the left join later
select * from org1 o1 inner join org2 o2 on o2.orgid = o1.orgid
)
select
*,
count(*) over (partition by WORK_STREET, WORKZIP) as cnt,
case when o.ARB_REF is not null then 'Yes' else 'No' end as result
from
WORK w left outer join org_data o on o.ARB_REF = w.ARB_REF

Fetch data from 3 three tables whichever is not null

I am trying to find the available address details from three tables.
When table 1 has the address details then get it from table1
If table 1 address has null value then consider table2,
If table 2 address has null value then consider table3, else display table1 address (null)
There are foreign keys in table 1 which can be used to join table 2 and 3 but they can be null as well in which case only data from table 1 to be considered.
In my query, I am able to join the tables when the foreign keys are available but in case they are null, the query doesn’t work!
I am not sure if I can add a ‘Case’ statement to ignore the ‘Join’ conditions in case the foreign keys are null.
Can someone please assist?
My Query is below :
SELECT donor.donor_num,
CASE
--WHEN donor.addr1 IS NULL THEN paraddress.addr1
--WHEN paraddress.addr1 IS NULL THEN enrparaddr.addr1
WHEN donor.addr1 IS NULL THEN enrparaddr.addr1
ELSE donor.addr1
END AS Address1,
CASE
--WHEN donor.addr2 IS NULL THEN paraddress.addr2
--WHEN paraddress.addr2 IS NULL THEN enrparaddr.addr2
WHEN donor.addr2 IS NULL THEN enrparaddr.addr2
ELSE donor.addr2
END AS Address2
FROM donor
JOIN enrparaddr ON enrparaddr.par_code = donor.enrol_code
--JOIN paraddress ON paraddress.par_code = donor.par_code
WHERE donor_num = '17206'
Please see attached image for the three tables
You can try below - using FULL OUTER JOIN & coalesce() function
SELECT donor.donor_num,
coalesce(donor.addr1,paraddress.addr1,enrparaddr.addr1) AS Address1,
coalesce(donor.addr2,paraddress.addr2,enrparaddr.addr2) AS Address2
FROM donor
FULL OUTER JOIN enrparaddr ON enrparaddr.par_code = donor.enrol_code
FULL OUTER JOIN paraddress ON paraddress.par_code = donor.par_code
WHERE donor_num = '17206'
SELECT donor.donor_num,CASE WHEN donor.addr1 IS NULL
THEN enrparaddr.addr1
ELSE donor.addr1
END AS Address1,
CASE WHEN donor.addr2 IS NULL
THEN enrparaddr.addr2
ELSE donor.addr2
END AS Address2
FROM donor
left join enrparaddr ON enrparaddr.par_code = donor.enrol_code
WHERE donor_num = '17206'
I would recommend:
SELECT d.donor_num,
coalesce(d.addr1, pp.addr1, epe.addr1) AS Address1,
coalesce(d.addr2, pp.addr2, epe.addr2) AS Address2
FROM donor d LEFT JOIN
paraddress pp
ON pp.par_code = d.par_code LEFT JOIN
enrparaddr epe
ON epe.par_code = d.enrol_code AND
pp.par_code IS NULL
WHERE d.donor_num = 17206 -- do not use single quotes for numbers
Notes:
You want a LEFT JOIN because you want all rows in donors.
You should be joining the tables in the order used for the COALESCE().
The second JOIN condition can be limited to cases where the first does not match.
Number constants should not use single quotes.
You can do this with simple Case .. When Statement:
Select Case
When A.ID is NULL And B.ID is NULL And C.ID is NULL Then -- when all columns contain null
NULL
When A.ID is NULL And B.ID is NULL Then
C.ID
When B.ID is NULL and C.ID is NULL Then
A.ID
When A.ID is NULL And C.ID is NULL Then
B.ID
End As ID
From A, B, C

Selecting different columns from databases

Hello I have two databases and each has the same tables. For example I have table called world and it has 4 columns: pkey1, pkey2,companyid, company_name
I made a query which searches for rows which have the same pkey1 and pkey2 but one or many of their other property is different in the 2 tables. My question is how can I see only the different properties?
Here is my query it selects the rows which have the same pkey1 and pkey2 how can I upgrade it to see the columns where there is difference in both databases and of course if there is no difference the result of the query should return NULL in the column here is an example what I want to achieve:
in first database (1,1,345,'Ron'), second database (1,1,377,'Ron') the result should be (1,1,345,null)
Basically to reference data in a different database, you'll need a database link, since you are using PostgreSQL, this documentation should help;
https://www.postgresql.org/docs/current/static/dblink.html
You'll need to use this command to create the link (in this case with a name);
SELECT dblink_connect('CONNECTIONNAME', 'REMOTEDBCONNECTIONSTRING');
Then you can use this new connection via a select query;
SELECT *
FROM dblink('CONNECTIONNAME','SELECT * FROM foo') AS t(a int, b text, c text[]);
And replace 'foo' with your 'world' table name, then change the AS into the variables that relate to pkey1, pkey2,companyid, company_name etc.
If your databases are linked, you can join both tables and with "case" statement check if the value has changed:
select a.pkey1, a.pkey2,
case when a.companyid <> b.companyid then a.companyid else null end as companyid,
case when a.company_name <> b.company_name then a.company_name else null end as company_name
from db1.dbo.world a
inner join db2.dbo.world b on a.pkey1 = b.pkey1 and a.pkey2 = b.pkey2
If you want to omit rows with no difference you can use "except":
select a.pkey1, a.pkey2,
case when a.companyid <> b.companyid then a.companyid else null end as companyid,
case when a.company_name <> b.company_name then a.company_name else null end as company_name
from (
select pkey1, pkey2, companyid, company_name
from db1.dbo.world
except
select pkey1, pkey2, companyid, company_name
from db2.dbo.world) a
inner join db2.dbo.world b on a.pkey1 = b.pkey1 and a.pkey2 = b.pkey2

Insert case when into table from joined table

I'm new to SQL and I'm having some trouble solving a problem. I'm rewriting a script where I can match with customers who have received an email. Previously I have been using session tables as below:
DECLARE GLOBAL TEMPORARY TABLE EMAIL_SENDS
(
ACCOUNT_NUMBER INT
)
WITH REPLACE
ON COMMIT PRESERVE ROWS
;
INSERT INTO SESSION.EMAIL_SENDS
SELECT ACCOUNT_NUMBER
FROM SENT_DATA A
JOIN MAIN_TABLE B
ON A.CLIENT_ID_SUBKEY = B.CUST_ID
OR A.CLIENT_ID_SUBKEY = B.OLD_ID
WHERE SEND_ID = 123456
GROUP BY ACCOUNT_NUMBER
;
Then when pulling the data I have just used CASE WHEN C.ACCOUNT_NUMBER IS NOT NULL THEN 1 ELSE 0 END joining the MAIN_TABLE with the EMAIL_SENDS to flag who has and hasn't received the email.
However I would like to improve the process, and add a column to the MAIN_TABLE stating who has received an email and who hasn't.
This is my script so far:
ALTER TABLE MAIN_TABLE
ADD EMAILED INT
;
INSERT INTO MAIN_TABLE
SELECT EMAILED
CASE WHEN ACCOUNT_NUMBER IS NOT NULL THEN 1 ELSE 0 END
FROM (SENT_DATA A
JOIN MAIN_TABLE B
ON A.CLIENT_ID_SUBKEY = B.CUST_ID
OR A.CLIENT_ID_SUBKEY = B.OLD_ID
WHERE SEND_ID = 123456
GROUP BY ACCOUNT_NUMBER
)
;
As I'm new to SQL I'm not able to figure out where I'm going wrong (even though it's probably obvious to anyone proficient at it).
try this. replace column names from main table to with this (EMAILED,ACCOUNT_NUMBER)
INSERT INTO MAIN_TABLE (EMAILED,ACCOUNT_NUMBER)
SELECT EMAILED,
CASE WHEN ACCOUNT_NUMBER IS NOT NULL THEN 1 ELSE 0 END
FROM (SENT_DATA A
JOIN MAIN_TABLE B
ON A.CLIENT_ID_SUBKEY = B.CUST_ID
OR A.CLIENT_ID_SUBKEY = B.OLD_ID
WHERE SEND_ID = 123456
GROUP BY ACCOUNT_NUMBER
)
;

If-Else Statement in T-SQL

I'm trying to alter the results of a Transact-SQL (MS SQL Server) report that is currently showing:
CompanyA DVCE3
CompanyB DVCE2
CompanyC DVCE3
CompanyD NULL
CompanyE DVCE3
and I would like it instead to show:
CompanyA 36
CompanyB 24
CompanyC 36
CompanyD
CompanyE 36
I'm sure the answer to this is to use some kind of if/else statement or a case statement, but I'm not sure of the syntax of this in T-SQL or where it should go in my query.
My basic query looks like this:
SELECT
companyName
, term
FROM tableA a
JOIN tableB b on a.id = b.id ...
WHERE
customerNumber IS NOT NULL
AND companyName != 'TEST'... ;
Thanks for your help.
Replace your "term" field with the following:
CASE WHEN term='DVCE3' THEN '36' WHEN term='DVCE2' THEN '24' ELSE '' END as term
I'll rewrite it for readability:
CASE
WHEN term='DVCE3' THEN '36'
WHEN term='DVCE2' THEN '24'
ELSE ''
END as term
If you only have a few replacements you could stick them in a case statement as below.
SELECT
companyName
,CASE term WHEN 'DVCE3' THEN '36' WHEN 'DVCE2' THEN '24' ELSE '' END AS term
FROM tableA a
JOIN tableB b on a.id = b.id ...
WHERE
customerNumber IS NOT NULL
AND companyName != 'TEST'... ;
If you have more or you will be repeating this logic in other queries you could maybe set up a mapping table (either a permanent table, view, or an inline TVF) that you can then join onto.
A Case statement will work. However a better answer might be to place that data into a table and do a join or just place it into a field in your company table. This makes it MUCH more extensible in the long run.
CREATE TABLE CompanyTerms (
id INT,
CompanyName NVARCHAR(100) NOT NULL,
Term NVARCHAR(100) NULL
)
...
SELECT
companyName
, c.Term
FROM tableA a
JOIN tableB b on a.id = b.id ...
JOIN CompanyTerm c ON c.id = a.id
WHERE
customerNumber IS NOT NULL
AND companyName != 'TEST'... ;