SQL using inner join - sql

So this is the situation I have. I have 3 tables (tblEmployeesinfo , sqlSumrepMTC, sqlSumrepMTC15th) I display this info using inner join:
SELECT
SQLSummRepMTC."RepCompany", SQLSummRepMTC."WHTax",
SQLSummRepMTC."Company", SQLSummRepMTC."MonthName",
SQLSummRepMTC."YearVal", SQLSummRepMTC."Basis",
tblEmployeesInfo."LastName", tblEmployeesInfo."FirstName",
tblEmployeesInfo."Company", tblEmployeesInfo."MInitial",
tblEmployeesInfo."Division", sqlSumrepMTC15th."WHTax",
sqlSumrepMTC15th."Basis"
FROM
{
oj ("BIOMETRICS"."dbo"."SQLSummRepMTC" SQLSummRepMTC INNER JOIN
"BIOMETRICS"."dbo"."tblEmployeesInfo" tblEmployeesInfo
ON SQLSummRepMTC."EmployeeNo" = tblEmployeesInfo."EmployeeNo")
INNER JOIN "BIOMETRICS"."dbo"."sqlSumrepMTC15th" sqlSumrepMTC15th
ON tblEmployeesInfo."EmployeeNo" = sqlSumrepMTC15th."EmployeeNo"
}
ORDER BY
SQLSummRepMTC."Basis" ASC,
tblEmployeesInfo."Company" ASC,
tblEmployeesInfo."LastName" ASC
Let's say one employee has his record on sqlSumrepMTC with its field Taxvalue of 50 but he does not exist on sqlSumrepMTC15th my problem is that this record will not be displayed in the inner join since it does not have value on both tables. What i want to achieve is just display a 0 value when it does not exist in the other table. This is my report looks like.
Employeeno employeename 15th 30th
01 james 10 20
02 Chris NULL 50
first record will appear in the report since it has both record existing in the two tables, the second will not since its null in the first table. I just need it to appear in the report if one value is null or is missing from the other. Thanks in advance

You have two joins! Thus, if there is no record in sqlSumrepMTC15th you need to replace the second join with LEFT JOIN. If it is possible, that there is no join record in sqlSumrepMTC15th AND tblEmployeesInfo, you need to replace both joins with LEFT JOIN.
Furthermore, you can replace NULL by
SELECT CASE
WHEN attribute IS NULL
THEN 0
ELSE attribute
END AS resultColumName,
nextAttribute
FROM ...

Related

SQL query for crystal reports produces duplicate results

I created 3 tables TstInvoice, TstProd, TstPersons and added some data:
INVOICE_NBR CLIENT_NR VK_CONTACT
A10304 003145 AT
A10305 000079 EA
A10306 004458 AT
A10307 003331 JDJ
PROD_NR INVOICE_NBR
P29366 A10304
P29367 A10304
P29368 A10305
P29369 A10306
P29370 A10306
P29371 A10307
PERS_NR INITIALEN STATUS PERSOON
0001 AT 7 Alice Thompson
0002 EA 1 Edgar Allen
0003 JDJ 1 John Doe Joe
0004 AT 1 Arthur Twins
The parameter that is passed to the crystal report is the INVOICE_NBR.
On my crystal report I put some fields from the databases and one sql expression:
(
SELECT "TstPersons"."PERSOON" FROM "TstPersons"
WHERE "TstPersons"."INITIALEN" = "TstInvoice"."VK_CONTACT" AND "TstPersons"."STATUS" = 1
)
The full query that is generated:
SELECT "TstInvoice"."INVOICE_NBR", "TstInvoice"."CLIENT_NR", "TstPersons"."STATUS", "TstPersons"."PERSOON", "TstProd"."PROD_NR", "TstProd"."INVOICE_NBR", (
SELECT "TstPersons"."PERSOON" FROM "TstPersons"
WHERE "TstPersons"."INITIALEN" = "TstInvoice"."VK_CONTACT" AND "TstPersons"."STATUS" = 1
)
FROM ("GCCTEST"."dbo"."TstInvoice" "TstInvoice" INNER JOIN "GCCTEST"."dbo"."TstProd" "TstProd" ON "TstInvoice"."INVOICE_NBR"="TstProd"."INVOICE_NBR") INNER JOIN "GCCTEST"."dbo"."TstPersons" "TstPersons" ON "TstInvoice"."VK_CONTACT"="TstPersons"."INITIALEN"
WHERE "TstInvoice"."INVOICE_NBR"='A10304'
The result is as shown in the screenshot:
As you can see the TstPersons.PERSOON field is populated with Alice Thompson and the sql expression field is correctly populated with Arthur Twins. However, I would like only to see the prod_nr once. With this query it produces the prod numbers twice because of the double entry for "AT" despite the fact that I ask for only status 1. I could just delete the old entry but I want to know if it's possible this way.
* edit * I added the status = 1 to the "record selection formula editor" and that seems to work. Not need the sql expression field at all. Not sure if this is the correct way to go though.
So now it looks like this:
SELECT "TstInvoice"."INVOICE_NBR", "TstInvoice"."CLIENT_NR", "TstPersons"."STATUS", "TstPersons"."PERSOON", "TstProd"."PROD_NR", "TstProd"."INVOICE_NBR"
FROM ("GCCTEST"."dbo"."TstInvoice" "TstInvoice" INNER JOIN "GCCTEST"."dbo"."TstProd" "TstProd" ON "TstInvoice"."INVOICE_NBR"="TstProd"."INVOICE_NBR") INNER JOIN "GCCTEST"."dbo"."TstPersons" "TstPersons" ON "TstInvoice"."VK_CONTACT"="TstPersons"."INITIALEN"
WHERE "TstInvoice"."INVOICE_NBR"='A10304' AND "TstPersons"."STATUS"=1
You have a very weak join in your query due to the duplicate values found in the INITIALEN column. Using the STATUS = 1 criteria is a work-around more than a solution because if you ever need to report on an invoice where the contact has a status other than 1, you will need to modify the report's design to allow your join to work because the STATUS value is not found on the invoice to allow a proper join to occur.
You are also running a risk of this work-around breaking down completely should you have another contact with both the same initials and status values as another.
The correct way to solve this problem would be to join TstInvoice to TstPersons through a field that has unique values. The PERS_NR column appears to be a good choice for this.
This is also going to require a redesign of the TstInvoice table to include the PERS_NR column as a Foreign Key.
A stronger join between invoices and persons would also remove the need for that sub-query in you selection statement. This would simplify your query down to the following:
SELECT "TstInvoice"."INVOICE_NBR", "TstInvoice"."CLIENT_NR", "TstPersons"."STATUS", "TstPersons"."PERSOON", "TstProd"."PROD_NR", "TstProd"."INVOICE_NBR"
FROM "GCCTEST"."dbo"."TstInvoice" "TstInvoice"
INNER JOIN "GCCTEST"."dbo"."TstProd" "TstProd"
ON "TstInvoice"."INVOICE_NBR"="TstProd"."INVOICE_NBR"
INNER JOIN "GCCTEST"."dbo"."TstPersons" "TstPersons"
ON "TstInvoice"."PERS_NR"="TstPersons"."PERS_NR"
WHERE "TstInvoice"."INVOICE_NBR"='A10304'

Left/Right join table with itself

I have a table which contains all the active loans for every month (for example 2017_01, 2017_02, 2017_03, etc). As I don't have another table which contains the Non Active loans (the closed ones) I have to manipulate the same table to get the closed loans for every specific months.
I have tried RIGHT OUTER JOIN in order to get the loans which are part of the previous YEAR_MONTH and have a NULL value in the next month, but as the table is joining itself using the LOAN_NUMBER field as a key, I am not getting the desired results.
Any idea of what I can do?
Ps: In other cases I needed to do that I used the "WHERE NOT EXISTS" clause, but I had two different tables.
My query is:
SELECT DM07MD.LOAN_NUMBER, DM07MD2.LOAN_NUMBER AS L2
FROM [dbo].[DM_07MONTHLY_DATA] DM07MD
LEFT OUTER JOIN [dbo].[DM_07MONTHLY_DATA] DM07MD2
ON DM07MD.LOAN_NUMBER = DM07MD2.LOAN_NUMBER
AND DM07MD.YYYY_MM = '2017_01'
WHERE DM07MD.S90T01_CLIENT_SEGMENT IN ('PI', 'MICRO')
AND DM07MD.S90T01_IS_RESTRUCTURED = 1
AND DM07MD2.LOAN_NUMBER IS NULL
AND DM07MD.YYYY_MM = '2017_02'
You can get the same by using exists,
SELECT DM07MD.LOAN_NUMBER FROM [dbo].[DM_07MONTHLY_DATA] DM07MD where DM07MD.YYYY_MM = '2017_02' and not exists
( SELECT 1 FROM [dbo].[DM_07MONTHLY_DATA] DM07MD2 where DM07MD.YYYY_MM = '2017_01' and DM07MD.LOAN_NUMBER=DM07MD2.LOAN_NUMBER )

SQL left join gives wrong results

In table A (i.e. Charges) I have my data and in B (i.e gdh) there are mappings.
For some reason my query doesn't show rows without mappings with null value.
Any thoughts?
select a.chargeable_object, a.debitor, a.source_bu, a.target_cc, a.target_bu, b.L5_CLUSTER, sum(a.charge)
from charges a
left join gdh b on a.target_cc = b.department_id
where a.account not like ('H%')
and a.chargeable_object is not null
and a.source_bu in ('301','161','303')
and a.debitor not in ('0315X02', '0961901', '0972023', '0972024',......)
group by a.chargeable_object, a.debitor, a.source_bu, a.target_cc, a.target_bu, b.L5_CLUSTER
It would help to see some example data. Anyhow does the column a.target_cc contains null values? I would expect that those would be filtered out.

SQL: return 0 count in case no record is found

A very simple issue as it appears but somehow not working for me on Oracle 10gXE.
Based on my SQLFiddle, I have to show all staff names and count if present or 0 if no record found having status = 2
How can I achieve it in a single query without calling Loop in my application side.
SELECT S.NAME,ISTATUS.STATUS,COUNT(ISTATUS.Q_ID) as TOTAL
FROM STAFF S
LEFT OUTER JOIN QUESTION_STATUS ISTATUS
ON S.ID = ISTATUS.DONE_BY
AND ISTATUS.STATUS = 2 <--- instead of WHERE
GROUP BY S.NAME,ISTATUS.STATUS
By filtering in the WHERE clause, you filter too late, and you remove STAFF rows that you do want to see. Moving the filter into the join condition means only QUESTION_STATUS rows get filtered out.
Note that STATUS is not really a useful column here, since you won't ever get any result other than 2 or NULL, so you could omit it:
SELECT S.NAME,COUNT(ISTATUS.Q_ID) as TOTAL
FROM STAFF S
LEFT OUTER JOIN QUESTION_STATUS ISTATUS
ON S.ID = ISTATUS.DONE_BY
AND ISTATUS.STATUS = 2
GROUP BY S.NAME
I corrected your sqlfiddle: http://sqlfiddle.com/#!4/90ba0/12
The rule of thumb is that the filters must appear in the ON condition of the table they depend on.
Move filter into the LEFT JOIN , also use COALESCE to have your results display 0 instead of null as you requested in your question
select S.NAME,COALESCE(ISTATUS.STATUS,0),COUNT(ISTATUS.Q_ID) as TOTAL
from STAFF S
LEFT OUTER JOIN QUESTION_STATUS ISTATUS
ON S.ID = ISTATUS.DONE_BY
AND ISTATUS.STATUS =2
GROUP BY S.NAME,ISTATUS.STATUS

outer query to list only if its rowcount equates to inner subquery

Need help on a query using sql server 2005
I am having two tables
code
chargecode
chargeid
orgid
entry
chargeid
itemNo
rate
I need to list all the chargeids in entry table if it contains multiple entries having different chargeids
which got listed in code table having the same charge code.
data :
code
100,1,100
100,2,100
100,3,100
101,11,100
101,12,100
entry
1,x1,1
1,x2,2
2,x3,2
11,x4,1
11,x5,1
using the above data , it query should list chargeids 1 and 2 and not 11.
I got the way to know how many rows in entry satisfies the criteria, but m failing to get the chargeids
select count (distinct chargeId)
from entry where chargeid in (select chargeid from code where chargecode = (SELECT A.chargecode
from code as A join code as B
ON A.chargecode = B.chargeCode and A.chargetype = B.chargetype and A.orgId = B.orgId AND A.CHARGEID = b.CHARGEid
group by A.chargecode,A.orgid
having count(A.chargecode) > 1)
)
First off: I apologise for my completely inaccurate original answer.
The solution to your problem is a self-join. Self-joins are used when you want to select more than one row from the same table. In our case we want to select two charge IDs that have the same charge code:
SELECT DISTINCT c1.chargeid, c2.chargeid FROM code c1
JOIN code c2 ON c1.chargeid != c2.chargeid AND c1.chargecode = c2.chargecode
JOIN entry e1 ON e1.chargeid = c1.chargeid
JOIN entry e2 ON e2.chargeid = c2.chargeid
WHERE c1.chargeid < c2.chargeid
Explanation of this:
First we pick any two charge IDs from 'code'. The DISTINCT avoids duplicates. We make sure they're two different IDs and that they map to the same chargecode.
Then we join on 'entry' (twice) to make sure they both appear in the entry table.
This approach gives (for your example) the pairs (1,2) and (2,1). So we also insist on an ordering; this cuts to result set down to just (1,2), as you described.