SQL Multiple joins - must be an easier way - sql

I have a table called Grades that we store pupils grades into for each year and term they sit exams. We then display this as an NCL, GCSE or Point grades. To find the NCL/GCSE equivalent grade we do a lookup on a different table that maps points to the correct GCSE/NCL equivalent grade.
However, this means my query has numerous joins to return a matching GCSE/NCL grade for our table of grades, I'm sure there's got to be an easier way
The code I have is below:
SELECT
Grades.GradeID, Grades.PupilID, Grades.GradeType, Grades.KeyStage2, Grades.Y7T1,
Grades.Y7T2, Grades.Y7T3, Grades.Y8T1, Grades.Y8T2, Grades.Y8T3, Grades.Y9T1, Grades.Y9T2,
Grades.Y9T3, Grades.Y10T1, Grades.Y10T2, Grades.Y10T3, Grades.Y11T1, Grades.Y11T2,
Grades.Y11T3, GradesToPoints.GCSEGrade AS KS2,
GradesToPoints_Y7T2.GCSEGrade AS [Year7 Term2],
GradesToPoints_Y7T3.GCSEGrade AS [Year7 Term3],
GradesToPoints_Y7T1.GCSEGrade AS [Year7 Term1],
GradesToPoints_Y8T1.GCSEGrade AS [Year8 Term1],
GradesToPoints_Y8T2.GCSEGrade AS [Year8 Term2],
GradesToPoints_Y8T3.GCSEGrade AS [Year8 Term3],
GradesToPoints_Y9T1.GCSEGrade AS [Year9 Term1],
GradesToPoints_Y9T2.GCSEGrade AS [Year9 Term2],
GradesToPoints_Y9T3.GCSEGrade AS [Year9 Term3],
GradesToPoints_Y10T1.GCSEGrade AS [Year10 Term1],
GradesToPoints_Y10T2.GCSEGrade AS [Year10 Term2],
GradesToPoints_Y10T3.GCSEGrade AS [Year10 Term3],
GradesToPoints_Y11T1.GCSEGrade AS [Year11 Term1],
GradesToPoints_Y11T2.GCSEGrade AS [Year11 Term2],
GradesToPoints_Y11T3.GCSEGrade AS [Year11 Term3], Grades.Subject
FROM
Grades
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y11T3 ON Grades.Y11T3 = GradesToPoints_Y11T3.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y11T2 ON Grades.Y11T2 = GradesToPoints_Y11T2.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y11T1 ON Grades.Y11T1 = GradesToPoints_Y11T1.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y10T3 ON Grades.Y10T3 = GradesToPoints_Y10T3.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y10T2 ON Grades.Y10T2 = GradesToPoints_Y10T2.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y10T1 ON Grades.Y10T1 = GradesToPoints_Y10T1.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y9T3 ON Grades.Y9T3 = GradesToPoints_Y9T3.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y9T2 ON Grades.Y9T2 = GradesToPoints_Y9T2.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y8T3 ON Grades.Y8T3 = GradesToPoints_Y8T3.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y8T2 ON Grades.Y8T2 = GradesToPoints_Y8T2.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y8T1 ON Grades.Y8T1 = GradesToPoints_Y8T1.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y7T3 ON Grades.Y7T3 = GradesToPoints_Y7T3.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y7T2 ON Grades.Y7T2 = GradesToPoints_Y7T2.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y7T1 ON Grades.Y7T1 = GradesToPoints_Y7T1.Points
LEFT OUTER JOIN
GradesToPoints ON Grades.KeyStage2 = GradesToPoints.Points
LEFT OUTER JOIN
GradesToPoints AS GradesToPoints_Y9T1 ON Grades.Y9T1 = GradesToPoints_Y9T1.Points
WHERE
(Grades.PupilID = #PupilID) AND (Grades.Subject = #Subject)

Your problem is that your data model is not properly normalized.
Your grades table seems to have 1 record for each student, with a column for each grade.
Instead, your grades table should have 1 record for each grade, with an extra column to denote the type of grade, Y7T1, Y7T2, etc. This also increases flexibility: you won't have to change the database structure when adding or removing certain grades.

Related

Looking to add in a Count query with Group by INTO an existing working query

Goal:
I wish to get the Count of how many times a WorkItem was re-assigned
From what I understand the proper query is the following:
SELECT
WorkItemDimvw.Id,
COUNT(WorkItemAssignedToUserFactvw.WorkItemAssignedToUser_UserDimKey) AS Assignments
FROM WorkItemDimvw INNER JOIN WorkItemAssignedToUserFactvw
ON WorkItemDimvw.WorkItemDimKey = WorkItemAssignedToUserFactvw.WorkItemDimKey
GROUP BY WorkItemDimvw.Id
The EXISTING query is below and I'm wondering / forgeting if I should:
Just add in COUNT(WorkItemAssignedToUserFactvw.WorkItemAssignedToUser_UserDimKey) AS Assignments since joins are existing, except it is group by WorkItemDimvw.Id
Should it instead be a subquery in the Select below?
Query:
SELECT
SRD.ID,
SRD.Title,
SRD.Description,
SRD.EntityDimKey,
WI.WorkItemDimKey,
IATUFact.DateKey
FROM
SLAConfigurationDimvw
INNER JOIN SLAInstanceInformationFactvw
ON SLAConfigurationDimvw.SLAConfigurationDimKey = SLAInstanceInformationFactvw.SLAConfigurationDimKey
RIGHT OUTER JOIN ServiceRequestDimvw AS SRD
INNER JOIN WorkItemDimvw AS WI
ON SRD.EntityDimKey = WI.EntityDimKey
LEFT OUTER JOIN WorkItemAssignedToUserFactvw AS IATUFact
ON WI.WorkItemDimKey = IATUFact.WorkItemDimKey
AND IATUFact.DeletedDate IS NULL
The trick is to aggregate the data on a sub query, before you join it.
SELECT
SRD.ID,
SRD.Title,
SRD.Description,
SRD.EntityDimKey,
WI.WorkItemDimKey,
IATUFact.DateKey,
IATUFact.Assignments
FROM
SLAConfigurationDimvw
INNER JOIN
SLAInstanceInformationFactvw
ON SLAConfigurationDimvw.SLAConfigurationDimKey = SLAInstanceInformationFactvw.SLAConfigurationDimKey
RIGHT OUTER JOIN
ServiceRequestDimvw AS SRD
ON <you're missing something here>
INNER JOIN
WorkItemDimvw AS WI
ON SRD.EntityDimKey = WI.EntityDimKey
LEFT OUTER JOIN
(
SELECT
WorkItemDimKey,
DateKey,
COUNT(WorkItemAssignedToUser_UserDimKey) AS Assignments
FROM
WorkItemAssignedToUserFactvw
WHERE
DeletedDate IS NULL
GROUP BY
WorkItemDimKey,
DateKey
)
IATUFact
ON WI.WorkItemDimKey = IATUFact.WorkItemDimKey

Management Hierarchy Query

Trying to create a SQL query that takes in an employee id, employee name, employee level, supervisor id, and supervisor name and returns all of the same data for each record with the org structure for a given employee down from the CEO.
Ideally, I am looking to achieve:
employee_id, name, employee_level, supervisor_id, supervisor_name, L1_supervisor_id, L1_supervisor_name, L2_supervisor_id, L2_supervisor_name...
I can get the management hierarchy from the CEO down using the following:
SELECT
lev01.employee_id id_01, lev01.name name_01, lev01.emp_type class_01,
lev02.employee_id id_02, lev02.name name_02, lev02.emp_type class_02,
lev03.employee_id id_03, lev03.name name_03, lev03.emp_type class_03,
lev04.employee_id id_04, lev04.name name_04, lev04.emp_type class_04,
lev05.employee_id id_05, lev05.name name_05, lev05.emp_type class_05,
lev06.employee_id id_06, lev06.name name_06, lev06.emp_type class_06,
lev07.employee_id id_07, lev07.name name_07, lev07.emp_type class_07,
lev08.employee_id id_08, lev08.name name_08, lev08.emp_type class_08,
lev09.employee_id id_09, lev09.name name_09, lev09.emp_type class_09,
lev10.employee_id id_10, lev10.name name_10, lev10.emp_type class_10,
lev11.employee_id id_11, lev11.name name_11, lev11.emp_type class_11,
lev12.employee_id id_12, lev12.name name_12, lev12.emp_type class_12,
lev13.employee_id id_13, lev13.name name_13, lev13.emp_type class_13,
lev14.employee_id id_14, lev14.name name_14, lev14.emp_type class_14,
lev15.employee_id id_15, lev15.name name_15, lev15.emp_type class_15,
lev16.employee_id id_16, lev16.name name_16, lev16.emp_type class_16,
lev17.employee_id id_17, lev17.name name_17, lev17.emp_type class_17,
lev18.employee_id id_18, lev18.name name_18, lev18.emp_type class_18
FROM emp_lst lev01
LEFT OUTER JOIN emp_lst lev02 ON lev01.employee_id = lev02.supervisor_id
LEFT OUTER JOIN emp_lst lev03 ON lev02.employee_id = lev03.supervisor_id
LEFT OUTER JOIN emp_lst lev04 ON lev03.employee_id = lev04.supervisor_id
LEFT OUTER JOIN emp_lst lev05 ON lev04.employee_id = lev05.supervisor_id
LEFT OUTER JOIN emp_lst lev06 ON lev05.employee_id = lev06.supervisor_id
LEFT OUTER JOIN emp_lst lev07 ON lev06.employee_id = lev07.supervisor_id
LEFT OUTER JOIN emp_lst lev08 ON lev07.employee_id = lev08.supervisor_id
LEFT OUTER JOIN emp_lst lev09 ON lev08.employee_id = lev09.supervisor_id
LEFT OUTER JOIN emp_lst lev10 ON lev09.employee_id = lev10.supervisor_id
LEFT OUTER JOIN emp_lst lev11 ON lev10.employee_id = lev11.supervisor_id
LEFT OUTER JOIN emp_lst lev12 ON lev11.employee_id = lev12.supervisor_id
LEFT OUTER JOIN emp_lst lev13 ON lev12.employee_id = lev13.supervisor_id
LEFT OUTER JOIN emp_lst lev14 ON lev13.employee_id = lev14.supervisor_id
LEFT OUTER JOIN emp_lst lev15 ON lev14.employee_id = lev15.supervisor_id
LEFT OUTER JOIN emp_lst lev16 ON lev15.employee_id = lev16.supervisor_id
LEFT OUTER JOIN emp_lst lev17 ON lev16.employee_id = lev17.supervisor_id
LEFT OUTER JOIN emp_lst lev18 ON lev17.employee_id = lev18.supervisor_id
WHERE lev01.supervisor_id IS NULL;
This falls short in two areas:
The query is a bit difficult to read and maintain. I'm sure there is a way to optimize/shorten it, but thus far I have not been able to find a suitable alternative.
Without the original records, it becomes a manual process to match these records back to the original table.
Any flavor of SQL will do, but I am using SQLite here.
You need recursive queries!
WITH RECURSIVE org_chart(employee_id, name, emp_type) AS (
SELECT employee_id, name, emp_type
FROM emp_lst
WHERE supervisor_id IS NULL
UNION ALL
SELECT employee_id, name, emp_type
FROM emp_lst e JOIN org_chart o ON e.supervisor_id = o.employee_id
)
SELECT * FROM org_chart;
Read more at the link I provided.
SQLite supports recursive queries since version 3.8.3 (2014-02-03).
Almost all other brands of SQL database support recursive query syntax too. See https://www.percona.com/blog/2014/02/11/wither-recursive-queries/
MySQL is the last one to add support, and that's coming in the next version 8.0.

Reduce query complexity

I have this multi join query, is there any way to reduce the number of joins? Or maybe to split the query to 2 parts but then still get the same result set?
Having too many joins makes the query execute very slowly and inefficently
SELECT
MD.EVENT_ID,
AUI.ATLAS_USER_ID,
EVENT_TIME,
EVENT_TYPE,
INTERACTION_TOKEN,
CC.COUNTRY_CODE,
AP.ADV_PROJECT_ID, AP.ADV_PROJECT_NAME,
AC.ADV_CAMPAIGN_ID,
ADV_CAMPAIGN_NAME,
PC.PRT_CAMPAIGN_ID, PC.PRT_CAMPAIGN_NAME,
IP.IP_ADDRESS,
OS.OS,
BR.BROWSER,
FU.FULL_USER_AGENT,
RAW_ACTION_ID,
SE.SELLER_NETWORK_ID,
RIURL.RAW_INPUT as URL,
RIREF.RAW_INPUT as REF_URL,
MVG1.MAP_VALUE as TABOOLA ,
MVG2.MAP_VALUE as APPNEXUS ,
MVG3.MAP_VALUE as ETAG ,
MVG4.MAP_VALUE as FACEBOOK ,
MVG5.MAP_VALUE as MEDIAMATH ,
MVG6.MAP_VALUE as COOKIEID ,
MVG7.MAP_VALUE as IDFA ,
MVG8.MAP_VALUE as ADVLOGIN ,
MVG9.MAP_VALUE as OPENX ,
MVG10.MAP_VALUE as ADTRUTH ,
MVG11.MAP_VALUE as GOOGLE ,
MVG12.MAP_VALUE as ANDROID_ADV_ID ,
MVG13.MAP_VALUE as SDGUPI ,
MVG15.MAP_VALUE as RMX
FROM
EVENT_124_2 BASE
INNER JOIN
atlas__atlas_events MD ON BASE.EVENT_ID = MD.EVENT_ID
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG1 ON MVG1.MAP_VALUE_GK = BASE.TABOOLA_HASH
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG2 ON MVG2.MAP_VALUE_GK = BASE.APPNEXUS_HASH
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG3 ON MVG3.MAP_VALUE_GK = BASE.ETAG_HASH
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG4 ON MVG4.MAP_VALUE_GK = BASE.FACEBOOK_HASH
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG5 ON MVG5.MAP_VALUE_GK = BASE.MEDIAMATH_HASH
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG6 ON MVG6.MAP_VALUE_GK = BASE.COOKIEID_HASH
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG7 ON MVG7.MAP_VALUE_GK = BASE.IDFA_HASH
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG8 ON MVG8.MAP_VALUE_GK = BASE.ADVLOGIN_HASH
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG9 ON MVG9.MAP_VALUE_GK = BASE.OPENX_HASH
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG10 ON MVG10.MAP_VALUE_GK = BASE.ADTRUTH_HASH
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG11 ON MVG11.MAP_VALUE_GK = BASE.GOOGLE_HASH
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG12 ON MVG12.MAP_VALUE_GK = BASE.ANDROID_ADV_ID_HASH
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG13 ON MVG13.MAP_VALUE_GK = BASE.SDGUPI_HASH
LEFT JOIN
LOOKUP_STG__MAP_VALUE MVG15 ON MVG15.MAP_VALUE_GK = BASE.RMX_HASH
LEFT JOIN
LOOKUP_STG__ATLAS_USER_ID AUI ON AUI.ATLAS_USER_ID_GK = MD.ATLAS_USER_ID
LEFT JOIN
GAYA__ADV_PROJECTS AP ON AP.ADV_PROJECT_ID = MD.ADV_PROJECT_ID
LEFT JOIN
GAYA__ADV_CAMPAIGNS AC ON AC.ADV_CAMPAIGN_ID = MD.ADV_CAMPAIGN_ID
LEFT JOIN
GAYA__PRT_CAMPAIGNS PC ON PC.PRT_CAMPAIGN_ID = MD.PRT_CAMPAIGN_ID
LEFT JOIN
LOOKUP_STG__RAW_INPUT RIURL ON RIURL.RAW_INPUT_GK = BASE.URL_HASH
LEFT JOIN
LOOKUP_STG__RAW_INPUT RIREF ON RIREF.RAW_INPUT_GK = BASE.REF_HASH
LEFT JOIN
LOOKUP_STG__OS OS ON OS.OS_GK = MD.COUNTRY_CODE
LEFT JOIN
LOOKUP_STG__COUNTRY_CODE CC ON CC.COUNTRY_CODE_GK = MD.COUNTRY_CODE
LEFT JOIN
LOOKUP_STG__BROWSER BR ON BR.BROWSER_GK = MD.BROWSER
LEFT JOIN
LOOKUP_STG__IP_ADDRESS IP ON IP.IP_ADDRESS_GK = MD.IP_ADDRESS
LEFT JOIN
LOOKUP_STG__SELLER_NETWORK_ID SE ON SE.SELLER_NETWORK_ID_GK = MD.SELLER_NETWORK_ID
LEFT JOIN
LOOKUP_STG__FULL_USER_AGENT FU ON FU.FULL_USER_AGENT_GK = MD.FULL_USER_AGENT
;
Do you have any indexes on your key columns? You might try to put bitmap indexes on each key column in the main fact table and also in the dimension tables. That should give you a considerable speedup.
You say that the number of joins makes the query inefficient. But what you should be looking at is whether the tables that are joined with have the proper indexes in them. You obviously need all those fields from the tables you join with, so you can't simply not join with them.
For every JOIN you make in the query, verify that there exists an INDEX on the field that is joined with. For instance:
INNER JOIN
atlas__atlas_events MD ON BASE.EVENT_ID = MD.EVENT_ID
Does the table atlas__atlas_events have an INDEX on the EVENT_ID column?
You need to verify this for every such JOIN in your query. If such an INDEX does not exist you should create one.
If you execute this query in SQL Server Management Studio and include the actual execution plan, you will probably already see indications that you are missing indexes.

Oracle and Left Outer Join

I am confused about this Hibernate generated Oracle Sql. There is one user in the database, but they don't have any badges, but I am doing a left outer join on everything. So the user should come back everytime, regardless of them having a badge. If I remove these lines, then it pulls back the user. Isn't left outer join suppose to bring someone back no matter what?
AND b4_.ACTIVE=1
AND B4_.STATUS='A'
AND UB2_.VISIBLE=1
and bl3_.ACTIVE=1
Hibernate Sql Ran In Sql Developer
select
this_.ID as ID0_11_,
this_.BIOGRAPHY as BIOGRAPHY0_11_,
this_.DATECREATED as DATECREA3_0_11_,
this_.EMAIL as EMAIL0_11_,
this_.ENABLED as ENABLED0_11_,
this_.FIRSTNAME as FIRSTNAME0_11_,
this_.HIDECONNECTORS as HIDECONN7_0_11_,
this_.HIDEEMAIL as HIDEEMAIL0_11_,
this_.HIDENAME as HIDENAME0_11_,
this_.LASTNAME as LASTNAME0_11_,
this_.PASSWORD as PASSWORD0_11_,
this_.SALT as SALT0_11_,
this_.TITLE as TITLE0_11_,
this_.USERNAME as USERNAME0_11_,
this_.WARNINGS as WARNINGS0_11_,
(SELECT
COUNT(*)
FROM
Followers f
WHERE
f.followerid = this_.Id) as formula0_11_,
assets6_.USERID as USERID13_,
asset7_.ID as ASSETID13_,
asset7_.ID as ID2_0_,
asset7_.ACTIVE as ACTIVE2_0_,
asset7_.DATECREATED as DATECREA3_2_0_,
asset7_.DATEMODIFIED as DATEMODI4_2_0_,
asset7_.DESCRIPTION as DESCRIPT5_2_0_,
asset7_.FILENAME as FILENAME2_0_,
asset7_.FILEPATH as FILEPATH2_0_,
asset7_.TITLE as TITLE2_0_,
asset7_.TYPE as TYPE2_0_,
roles8_.USERID as USERID14_,
role9_.ID as ROLEID14_,
role9_.ID as ID1_1_,
role9_.DISPLAYNAME as DISPLAYN2_1_1_,
role9_.NAME as NAME1_1_,
ub2_.USERID as USERID15_,
ub2_.ID as ID15_,
ub2_.ID as ID12_2_,
ub2_.BADGELEVELID as BADGELEV5_12_2_,
ub2_.DATECREATED as DATECREA2_12_2_,
ub2_.ISMANUAL as ISMANUAL12_2_,
ub2_.USERID as USERID12_2_,
ub2_.VISIBLE as VISIBLE12_2_,
bl3_.ID as ID9_3_,
bl3_.ACTIVE as ACTIVE9_3_,
bl3_.ASSETID as ASSETID9_3_,
bl3_.BADGEID as BADGEID9_3_,
bl3_.DATECREATED as DATECREA3_9_3_,
bl3_.DATEMODIFIED as DATEMODI4_9_3_,
bl3_.DESCRIPTION as DESCRIPT5_9_3_,
bl3_.FILTERS as FILTERS9_3_,
bl3_."ORDER" as ORDER7_9_3_,
(SELECT
COUNT(*)
FROM
USERBADGES ub
WHERE
ub.badgeLevelId = bl3_.Id) as formula1_3_,
(bl3_."ORDER" - 1) as formula2_3_,
asset12_.ID as ID2_4_,
asset12_.ACTIVE as ACTIVE2_4_,
asset12_.DATECREATED as DATECREA3_2_4_,
asset12_.DATEMODIFIED as DATEMODI4_2_4_,
asset12_.DESCRIPTION as DESCRIPT5_2_4_,
asset12_.FILENAME as FILENAME2_4_,
asset12_.FILEPATH as FILEPATH2_4_,
asset12_.TITLE as TITLE2_4_,
asset12_.TYPE as TYPE2_4_,
b4_.ID as ID10_5_,
b4_.ACTIVE as ACTIVE10_5_,
b4_.DATECREATED as DATECREA3_10_5_,
b4_.DATEMODIFIED as DATEMODI4_10_5_,
b4_.DESCRIPTION as DESCRIPT5_10_5_,
b4_.ENDDATE as ENDDATE10_5_,
b4_.NAME as NAME10_5_,
b4_.PUBLISHDETAILS as PUBLISHD8_10_5_,
b4_.STARTDATE as STARTDATE10_5_,
b4_.STATUS as STATUS10_5_,
b4_.UPDATEOWNERID as UPDATEO11_10_5_,
b4_.OWNERID as OWNERID10_5_,
(SELECT
COUNT(*)
FROM
BadgeLevels bl
WHERE
bl.badgeId = b4_.Id) as formula3_5_,
(CASE
WHEN (SELECT
COUNT(*)
FROM
BadgeLevels bl
WHERE
bl.badgeId = b4_.Id) > 1 THEN 'Ladder'
ELSE 'Single'
END) as formula4_5_,
user14_.ID as ID0_6_,
user14_.BIOGRAPHY as BIOGRAPHY0_6_,
user14_.DATECREATED as DATECREA3_0_6_,
user14_.EMAIL as EMAIL0_6_,
user14_.ENABLED as ENABLED0_6_,
user14_.FIRSTNAME as FIRSTNAME0_6_,
user14_.HIDECONNECTORS as HIDECONN7_0_6_,
user14_.HIDEEMAIL as HIDEEMAIL0_6_,
user14_.HIDENAME as HIDENAME0_6_,
user14_.LASTNAME as LASTNAME0_6_,
user14_.PASSWORD as PASSWORD0_6_,
user14_.SALT as SALT0_6_,
user14_.TITLE as TITLE0_6_,
user14_.USERNAME as USERNAME0_6_,
user14_.WARNINGS as WARNINGS0_6_,
(SELECT
COUNT(*)
FROM
Followers f
WHERE
f.followerid = user14_.Id) as formula0_6_,
websites15_.USERID as USERID16_,
website16_.ID as WEBSITEID16_,
website16_.ID as ID6_7_,
website16_.ACTIVE as ACTIVE6_7_,
website16_.DATECREATED as DATECREA3_6_7_,
website16_.DATEMODIFIED as DATEMODI4_6_7_,
website16_.DESCRIPTION as DESCRIPT5_6_7_,
website16_.NAME as NAME6_7_,
website16_.URL as URL6_7_,
uc1_.USERID as USERID17_,
uc1_.ID as ID17_,
uc1_.ID as ID17_8_,
uc1_.ACTIVE as ACTIVE17_8_,
uc1_.CONNECTORID as CONNECTO6_17_8_,
uc1_.dateCreated as dateCrea3_17_8_,
uc1_.dateModified as dateModi4_17_8_,
uc1_.META as META17_8_,
uc1_.USERID as USERID17_8_,
connector18_.ID as ID18_9_,
connector18_.ACTIVE as ACTIVE18_9_,
connector18_.DATECREATED as DATECREA3_18_9_,
connector18_.DISPLAYNAME as DISPLAYN4_18_9_,
connector18_.NAME as NAME18_9_,
user19_.ID as ID0_10_,
user19_.BIOGRAPHY as BIOGRAPHY0_10_,
user19_.DATECREATED as DATECREA3_0_10_,
user19_.EMAIL as EMAIL0_10_,
user19_.ENABLED as ENABLED0_10_,
user19_.FIRSTNAME as FIRSTNAME0_10_,
user19_.HIDECONNECTORS as HIDECONN7_0_10_,
user19_.HIDEEMAIL as HIDEEMAIL0_10_,
user19_.HIDENAME as HIDENAME0_10_,
user19_.LASTNAME as LASTNAME0_10_,
user19_.PASSWORD as PASSWORD0_10_,
user19_.SALT as SALT0_10_,
user19_.TITLE as TITLE0_10_,
user19_.USERNAME as USERNAME0_10_,
user19_.WARNINGS as WARNINGS0_10_,
(SELECT
COUNT(*)
FROM
Followers f
WHERE
f.followerid = user19_.Id) as formula0_10_
from
REWARD.USERS this_
left outer join
UserAssets assets6_
on this_.ID=assets6_.USERID
left outer join
REWARD.ASSETS asset7_
on assets6_.ASSETID=asset7_.ID
left outer join
UserRoles roles8_
on this_.ID=roles8_.USERID
left outer join
REWARD.ROLES role9_
on roles8_.ROLEID=role9_.ID
left outer join
REWARD.USERBADGES ub2_
on this_.ID=ub2_.USERID
left outer join
REWARD.BADGELEVELS bl3_
on ub2_.BADGELEVELID=bl3_.ID
left outer join
REWARD.ASSETS asset12_
on bl3_.ASSETID=asset12_.ID
left outer join
REWARD.BADGES b4_
on bl3_.BADGEID=b4_.ID
left outer join
REWARD.USERS user14_
on ub2_.USERID=user14_.ID
left outer join
UserWebsites websites15_
on user14_.ID=websites15_.USERID
left outer join
REWARD.WEBSITES website16_
on websites15_.WEBSITEID=website16_.ID
left outer join
REWARD.USERCONNECTORS uc1_
on this_.ID=uc1_.USERID
left outer join
REWARD.CONNECTORS connector18_
on uc1_.CONNECTORID=connector18_.ID
left outer join
REWARD.USERS USER19_
on uc1_.USERID=user19_.ID
WHERE
this_.ID=10100
and this_.ENABLED=1
AND UC1_.ACTIVE=1
AND UB2_.VISIBLE=1
and bl3_.ACTIVE=1
AND b4_.ACTIVE=1
AND B4_.STATUS='A'
Those users do come back but they come back as null for all the columns returned in the tables where the left join didn't find a proper join.
Due to how ANSI nulls work
b4_.ACTIVE=1 will be invalid for these records because null <> 1
Try restructuring your where block as follows:
AND (b4_.ACTIVE=1 or b4_.ACTIVE is null)
AND (B4_.STATUS='A' or B4_.STATUS is null)
AND (UB2_.VISIBLE=1 or UB2_.VISIBLE is null)
and (bl3_.ACTIVE=1 or bl3_.ACTIVE is null)
Another way to tackle this is add the prerequisites to your left joins. You can do like I did below and it will exclude the badges where ACTIVE <> 1 excluding bad badges and still return all users.
left outer join
REWARD.BADGES b4_
on bl3_.BADGEID=b4_.ID
AND b4_.ACTIVE=1

Sql Outer Join: Extracting values from multible tables

I am extracting data from multiple tables. mt query is as follows:
SELECT p.Record_Num as RecordNum
,p.GCD_ID as GCDID
,p.Project_Desc as ProjectDesc
,p.Proponent_Name as ProponentName
,st.Station_Name as StationName
,p.OpCentre as OpCentre
,s.Sector_Name as SectorName
,p.PLZone as PLZone
,f.Feeder_Desc as FeederDesc
,d.DxTx_Desc as DxTx
,op.Op_Control_Desc as OpControl
,t.Type_Desc as Type
,c.Conn_Desc as ConnectionKV
,ss.Status_Desc as Status
,p.MW as MW
,p.Subject as Subject
,p.Ip_Num as IpNum
,p.H1N_ID as H1NID
,p.NOMS_Slip_Num as NomsSlipNum
,p.NMS_Updated as NmsUpdated
,p.Received_Date as ReceivedDate
,p.Actual_IS_Date as ActualISDate
,p.Scheduled_IS_Date as ScheduledIsDate
,stst.Station_Name as UpStation
,ff.Feeder_Desc as UpFeeder
,p.HV_Circuit as HVCircuit
,p.SIA_Required as SIAReqd
FROM Project_Detail p,
Station st, Sector s, Feeder f, DxTx d, Operational_Control op, Type t,
Connection_Kv c, Status ss, Station stst, Feeder ff
WHERE
p.Station_ID = st.Station_ID and
p.Sector_ID = s.Sector_ID and
p.Feeder = f.Feeder_ID and
p.DxTx_ID = d.DxTx_ID and
p.OpControl_ID = op.Op_Control_ID and
p.Type_ID= t.Type_ID and
p.ConnKV_ID = c.Conn_ID and
p.Status_ID = ss.Status_ID and
p.UP_Station_ID = stst.Station_ID and
p.UP_Feeder_ID = ff.Feeder_ID
The problem with this query is if it doesnot find an associated value in the second table, it doesnot show the row.
for example : every project has feeders. so if a project_detail table has a feederid which doesnot have an association in the feeder table, then it wont show the row. also, there are times when the feeders are not assigned to a project.
i think i have to use outer joins to get the values. but i cannot figure out how to do that.
please help.
SELECT *
FROM Project_Detail p
LEFT JOIN
Station st
ON p.Station_ID = st.Station_ID
LEFT JOIN
Sector s
ON p.Sector_ID = s.Sector_ID
…
You need LEFT OR FULL OUTER JOINS instead of the inner joins you are now using with your where clause.
SELECT p.Record_Num as RecordNum
,p.GCD_ID as GCDID
,p.Project_Desc as ProjectDesc
,p.Proponent_Name as ProponentName
,st.Station_Name as StationName
,p.OpCentre as OpCentre
,s.Sector_Name as SectorName
,p.PLZone as PLZone
,f.Feeder_Desc as FeederDesc
,d.DxTx_Desc as DxTx
,op.Op_Control_Desc as OpControl
,t.Type_Desc as Type
,c.Conn_Desc as ConnectionKV
,ss.Status_Desc as Status
,p.MW as MW
,p.Subject as Subject
,p.Ip_Num as IpNum
,p.H1N_ID as H1NID
,p.NOMS_Slip_Num as NomsSlipNum
,p.NMS_Updated as NmsUpdated
,p.Received_Date as ReceivedDate
,p.Actual_IS_Date as ActualISDate
,p.Scheduled_IS_Date as ScheduledIsDate
,stst.Station_Name as UpStation
,ff.Feeder_Desc as UpFeeder
,p.HV_Circuit as HVCircuit
,p.SIA_Required as SIAReqd
FROM Project_Detail p
LEFT OUTER JOIN Station st ON p.Station_ID = st.Station_ID
LEFT OUTER JOIN Sector s ON p.Sector_ID = s.Sector_ID
LEFT OUTER JOIN Feeder f ON p.Feeder = f.Feeder_ID
LEFT OUTER JOIN DxTx d ON p.DxTx_ID = d.DxTx_ID
LEFT OUTER JOIN Operational_Control op ON p.OpControl_ID = op.Op_Control_ID
LEFT OUTER JOIN Type t ON p.Type_ID= t.Type_ID
LEFT OUTER JOIN Connection_Kv c ON p.ConnKV_ID = c.Conn_ID
LEFT OUTER JOIN Status ss ON p.Status_ID = ss.Status_ID
LEFT OUTER JOIN Station stst ON p.UP_Station_ID = stst.Station_ID
LEFT OUTER JOIN Feeder ff ON p.UP_Feeder_ID = ff.Feeder_ID