Oracle and Left Outer Join - sql

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

Related

I am converting following oracle query to bigquery but the result record counts are different

I am converting following oracle query to bigquery query but the results(record counts) are different, eventhough base tables involved in the query are having same number of records in both oracle and bq.
oracle :
SELECT
to_char(R_PROJECT_S.PROJECT_COPYRIGHT_YEAR),
R_PROJECT_S.PROJECT_TITLE,
to_char(R_PROJECT_S.EDITION),
R_PROJECT_S.CIRCULATION_DESC,
R_PROJECT_S.DISTRIBUTION_DESC,
R_PROJECT_S.PROJECT_ID,
DB.R_USAGE_INFO_S.OBJECT_ID,
UPPER(DB.R_INFO_S.PHOTOGRAPHER),
UPPER(DB.R_INFO_S.SOURCE_CAPTION),
ADMIN.BIC_APHEISBN00_BO_VW.BIC_ZCHEAU,
ADMIN.BIC_APHEISBN00_BO_VW.BIC_ZCHECPYR,
ADMIN.BIC_APHEISBN00_BO_VW.BIC_ZCHEED,
ADMIN.BIC_APHEISBN00_BO_VW.BIC_ZCHEPRDDE,
ADMIN.BIC_APHEISBN00_BO_VW.BIC_ZCHEGRDE,
ADMIN.BIC_APHEISBN00_BO_VW.BIC_ZCHSODE,
R_PROJECT_S.CHARGE_TO_ISBN,
ADMIN.BIC_APHEISBN00_BO_VW.BIC_ZCHEPTIT,
DB.R_INFO_S.SOURCE_NAME,
R_PROJECT_S.LANGUAGE_DESC,
R_PROJECT_S.PROJECT_FORMAT_DESC,
DB.R_USAGE_INFO_S.USAGE_ID,
DB.R_USAGE_INFO_S.PAGE,
DB.R_USAGE_INFO_S.CHAPTER,
DB.R_INFO_S.WORK_PROJECT_ID,
DB.R_INFO_S.IMAGE_TYPE_DESC,
DB.R_INFO_S.IMAGE_DESC,
DB.R_USAGE_INFO_S.PERMISSION_TYPE_DESC,
DB.R_USAGE_INFO_S.PERMISSION_STATUS_DESC,
DB.R_USAGE_INFO_S.PERMISSION_USAGE_DESC,
DB.R_USAGE_INFO_S.USAGE_LABEL,
DB.R_USAGE_INFO_S.QUOTED_COST,
DB.R_INFO_S.SOURCE_OBJECT_ID,
DB.R_USAGE_INFO_S.USAGE_TYPE_DESC,
GHEPM_TITLE_PSPP.TITLE_DESCRIPTION,
ADMIN.BIC_APHEISBN00_BO_VW.BIC_ZCHESOAB,
ADMIN.BIC_APHEISBN00_BO_VW.BIC_ZCHEGRCD
FROM
DB.R_PROJECT_S_VW R_PROJECT_S,
DB.R_USAGE_INFO_S,
DB.R_INFO_S,
ADMIN.BIC_APHEISBN00_BO_VW,
DB.GHEPM_TITLE GHEPM_TITLE_PSPP
WHERE
( R_PROJECT_S.PROJECT_ID=DB.R_USAGE_INFO_S.PROJECT_ID(+)
)
AND ( DB.R_USAGE_INFO_S.OBJECT_ID=DB.R_INFO_S.OBJECT_ID )
AND ( R_PROJECT_S.PROJECT_ID=ADMIN.BIC_APHEISBN00_BO_VW.BIC_ZCHETIIS(+) )
AND ( R_PROJECT_S.PROJECT_ID=DB.GHEPM_TITLE_PSPP.ISBN10(+) )
AND UPPER(DB.R_USAGE_INFO_S.USAGE_LABEL) NOT LIKE UNISTR('%KILL%')
BQ:
SELECT
CAST(R_PROJECT_S.PROJECT_COPYRIGHT_YEAR AS string) COPYRIGHT_YEAR,
R_PROJECT_S.PROJECT_TITLE,
CAST(R_PROJECT_S.EDITION AS string) EDITION,
R_PROJECT_S.CIRCULATION_DESC,
R_PROJECT_S.DISTRIBUTION_DESC,
R_PROJECT_S.PROJECT_ID,
R_USAGE_INFO_S.OBJECT_ID,
UPPER(R_INFO_S.PHOTOGRAPHER) PHOTOGRAPHER,
UPPER(R_INFO_S.SOURCE_CAPTION) SOURCE_CAPTION,
BIC_APHEISBN00_BO._BIC_ZCHEAU,
BIC_APHEISBN00_BO._BIC_ZCHECPYR,
BIC_APHEISBN00_BO._BIC_ZCHEED,
BIC_APHEISBN00_BO._BIC_ZCHEPRDDE,
BIC_APHEISBN00_BO._BIC_ZCHEGRDE,
BIC_APHEISBN00_BO._BIC_ZCHSODE,
R_PROJECT_S.CHARGE_TO_ISBN,
BIC_APHEISBN00_BO._BIC_ZCHEPTIT,
R_INFO_S.SOURCE_NAME,
R_PROJECT_S.LANGUAGE_DESC,
R_PROJECT_S.PROJECT_FORMAT_DESC,
R_USAGE_INFO_S.USAGE_ID,
R_USAGE_INFO_S.PAGE,
R_USAGE_INFO_S.CHAPTER,
R_INFO_S.WORK_PROJECT_ID,
R_INFO_S.IMAGE_TYPE_DESC,
R_INFO_S.IMAGE_DESC,
R_USAGE_INFO_S.PERMISSION_TYPE_DESC,
R_USAGE_INFO_S.PERMISSION_STATUS_DESC,
R_USAGE_INFO_S.PERMISSION_USAGE_DESC,
R_USAGE_INFO_S.USAGE_LABEL,
R_USAGE_INFO_S.QUOTED_COST,
R_INFO_S.SOURCE_OBJECT_ID,
R_USAGE_INFO_S.USAGE_TYPE_DESC,
GHEPM_TITLE_PSPP.TITLE_DESCRIPTION,
BIC_APHEISBN00_BO._BIC_ZCHESOAB,
BIC_APHEISBN00_BO._BIC_ZCHEGRCD
FROM
`domain-rr.oracle_DB_DB.R_info_s` R_INFO_S
inner join
`domain-rr.oracle_DB_DB.R_usage_info_s` R_USAGE_INFO_S
on
R_USAGE_INFO_S.OBJECT_ID=R_INFO_S.OBJECT_ID
right outer join
`domain-rr.DB_RPT.R_PROJECT_S_VW` R_PROJECT_S
on
R_PROJECT_S.PROJECT_ID=R_USAGE_INFO_S.PROJECT_ID
left outer join
`domain-rr.DB_RPT.BIC_APHEISBN00_BO_VW` BIC_APHEISBN00_BO
ON
R_PROJECT_S.PROJECT_ID=BIC_APHEISBN00_BO._BIC_ZCHETIIS
left outer join
`domain-rr.oracle_DB_DB.ghepm_title` GHEPM_TITLE_PSPP
ON
R_PROJECT_S.PROJECT_ID=GHEPM_TITLE_PSPP.ISBN10
AND UPPER(R_USAGE_INFO_S.USAGE_LABEL) NOT LIKE '%KILL%'
Oracle count - 1553437
BQ count - 2414413
Please help me on how to get counts are same on both oracle and bq
Thanks,
Naren
Had you used more readable, shortened table aliases several differences can be illuminated:
Oracle does not attempt any RIGHT JOIN;
GBQ should run UPPER(...) expression in WHERE not on last LEFT JOIN clause or move expression to INNER JOIN on ui table (but without testing may not make a difference but readability);
Table order may make a difference especially with use of both INNER and OUTER joins;
Oracle (using the older, outdated implicit joins)
...
FROM
GRDW.RMS_IMAGE_PROJECT_S_VW p,
GRDW.RMS_IMAGE_USAGE_INFO_S ui,
GRDW.RMS_IMAGE_INFO_S i,
BOADMIN.BIC_APHEISBN00_BO_VW b,
GRDW.GHEPM_TITLE g
WHERE
( p.PROJECT_ID = ui.PROJECT_ID(+) -- LEFT JOIN
)
AND ( ui.OBJECT_ID = i.OBJECT_ID ) -- INNER JOIN
AND ( p.PROJECT_ID = b.BIC_ZCHETIIS(+) ) -- LEFT JOIN
AND ( p.PROJECT_ID = g.ISBN10(+) ) -- LEFT JOIN
AND UPPER(ui.USAGE_LABEL) NOT LIKE UNISTR('%KILL%')
Google BigQuery (using current standard of explicit joins)
...
FROM
`pearson-rr.oracle_grdw_grdw.rms_image_info_s` i
INNER JOIN
`pearson-rr.oracle_grdw_grdw.rms_image_usage_info_s` ui
ON ui.OBJECT_ID = i.OBJECT_ID
RIGHT OUTER JOIN
`pearson-rr.GRDW_RPT.RMS_IMAGE_PROJECT_S_VW` p
ON p.PROJECT_ID = ui.PROJECT_ID
LEFT OUTER JOIN
`pearson-rr.GRDW_RPT.BIC_APHEISBN00_BO_VW` b
ON p.PROJECT_ID = b._BIC_ZCHETIIS
LEFT OUTER JOIN
`pearson-rr.oracle_grdw_grdw.ghepm_title` g
ON p.PROJECT_ID = g.ISBN10
AND UPPER(ui.USAGE_LABEL) NOT LIKE '%KILL%'
Therefore, to account for table order and appropriate JOIN, consider below adjusted Google BigQuery:
...
FROM
`pearson-rr.GRDW_RPT.RMS_IMAGE_PROJECT_S_VW` p
LEFT OUTER JOIN
`pearson-rr.oracle_grdw_grdw.rms_image_usage_info_s` ui
ON p.PROJECT_ID = ui.PROJECT_ID
INNER OUTER JOIN
`pearson-rr.oracle_grdw_grdw.rms_image_info_s` i
ON ui.OBJECT_ID = i.OBJECT_ID AND UPPER(ui.USAGE_LABEL) NOT LIKE '%KILL%'
LEFT OUTER JOIN
`pearson-rr.GRDW_RPT.BIC_APHEISBN00_BO_VW` b
ON p.PROJECT_ID = b._BIC_ZCHETIIS
LEFT OUTER JOIN
`pearson-rr.oracle_grdw_grdw.ghepm_title` g
ON p.PROJECT_ID = g.ISBN10

Is there a quick fix for a syntax error in my JOIN operation

I'm fairly new to sql and am probably over my head with this but I keep running into a syntax error in my join statement.
I am trying to get specific stats for a single character. I have added more parenthese to get rid of a missing operator error, and I have tried adding parenthese to only around the inner joins of the same tables. So far the join statement is the only thing throwing errors.
SELECT CHARACTER.CharacterName, CHARACTER.Alignment, INVENTORY.Equipped,
ITEMS.ItemName,
ITEMS.PhysDef, ITEMS.MDef, ITEMS.Dodge, ITEMS.Damage, ITEMS.CritMultiplier,
ITEMS.Range,
ITEMS.AttackSpeed, JOB_CHARACTER.JobLevel, RACE_CHARACTER.RacialLevel,
RACE.RaceName, RACE.Strength,
RACE.Skill, RACE.Vitality, RACE.Arcane, RACE.Spirit, RACE.Charisma,
RACE.Luck, JOB.JobName,
JOB.HP, JOB.AttackBonus, JOB.Agility, JOB.Might, JOB.SpellPower, JOB.Vital,
JOB.Nimble, JOB.Mental,
JOB.Curese, JOB.SpellCasting, JOB.ManaBase, JOB.ManaType, JOB.Ki,
SKILLS.Alchemy, SKILLS.Awareness,
SKILLS.Climb, SKILLS.Coach, SKILLS.Construction, SKILLS.Decieve,
SKILLS.DisarmMechanism,
SKILLS.DiscernTruth, SKILLS.Dishearten, SKILLS.Fly, SKILLS.Forge,
SKILLS.Gymnastics,SKILLS.Identify,
SKILLS.Leadership, SKILLS.Lore_9Realms, SKILLS.Lore_Alternative,
SKILLS.Lore_Arcane,
SKILLS.Lore_Arithmancy, SKILLS.Lore_Divine, SKILLS.Lore_Geography,
SKILLS.Lore_Nature,
SKILLS.Lore_Nobility, SKILLS.Lore_Religion, SKILLS.Lore_Spiritual,
SKILLS.Medical,
SKILLS.Performance, SKILLS.Ride, SKILLS.Steal, SKILLS.Stealth,
SKILLS.Subterfuge,
SKILLS.Swim, SKILLS.Tailor, SKILLS.UseContraption, SKILLS.Wilderness
FROM (((((((CHARACTER INNER JOIN RACE_CHARACTER ON
CHARACTER.CharacterID=RACE_CHARACTER.CharacterID)
LEFT JOIN JOB_CHARACTER ON CHARACTER.CharacterID=JOB_CHARACTER.CharacterID)
LEFT JOIN INVENTORY ON CHARACTER.CharacterID=INVENTORY.CharacterID)
INNER JOIN INVENTORY ON ITEMS.ItemID =INVENTORY.ItemID)
INNER JOIN JOB ON JOB.JobID=JOB_CHARACTER.JobID)
LEFT JOIN SKILLS ON JOB.JobID=SKILLS.JobID)
INNER JOIN RACE ON RACE.RaceID=RACE_CHARACTER.RaceID)
WHERE ((CHARACTER.CharacterID)=1) AND ((JOB.JobID)=3) AND
((RACE.RaceID)=6);
I expect this to output the stats for this single character, its name, and skills, however it is not currently outputting anything.
Your select statement is sourcing 8 fields from an ITEMS table:
SELECT
...
ITEMS.ItemName,
ITEMS.PhysDef,
ITEMS.MDef,
ITEMS.Dodge,
ITEMS.Damage,
ITEMS.CritMultiplier,
ITEMS.Range,
ITEMS.AttackSpeed,
...
However, the ITEMS table is not referenced by your from clause:
FROM
(
(
(
(
(
(
(
CHARACTER INNER JOIN RACE_CHARACTER ON
CHARACTER.CharacterID=RACE_CHARACTER.CharacterID
)
LEFT JOIN JOB_CHARACTER ON
CHARACTER.CharacterID=JOB_CHARACTER.CharacterID
)
LEFT JOIN INVENTORY ON
CHARACTER.CharacterID=INVENTORY.CharacterID
)
INNER JOIN INVENTORY ON ----------< INVENTORY table referenced twice
ITEMS.ItemID =INVENTORY.ItemID
)
INNER JOIN JOB ON
JOB.JobID=JOB_CHARACTER.JobID
)
LEFT JOIN SKILLS ON
JOB.JobID=SKILLS.JobID
)
INNER JOIN RACE ON
RACE.RaceID=RACE_CHARACTER.RaceID
)
I should imagine the SQL code should be changed to something like:
SELECT
CHARACTER.CharacterName,
CHARACTER.Alignment,
INVENTORY.Equipped,
ITEMS.ItemName,
ITEMS.PhysDef,
ITEMS.MDef,
ITEMS.Dodge,
ITEMS.Damage,
ITEMS.CritMultiplier,
ITEMS.Range,
ITEMS.AttackSpeed,
JOB_CHARACTER.JobLevel,
RACE_CHARACTER.RacialLevel,
RACE.RaceName,
RACE.Strength,
RACE.Skill,
RACE.Vitality,
RACE.Arcane,
RACE.Spirit,
RACE.Charisma,
RACE.Luck,
JOB.JobName,
JOB.HP,
JOB.AttackBonus,
JOB.Agility,
JOB.Might,
JOB.SpellPower,
JOB.Vital,
JOB.Nimble,
JOB.Mental,
JOB.Curese,
JOB.SpellCasting,
JOB.ManaBase,
JOB.ManaType,
JOB.Ki,
SKILLS.Alchemy,
SKILLS.Awareness,
SKILLS.Climb,
SKILLS.Coach,
SKILLS.Construction,
SKILLS.Decieve,
SKILLS.DisarmMechanism,
SKILLS.DiscernTruth,
SKILLS.Dishearten,
SKILLS.Fly,
SKILLS.Forge,
SKILLS.Gymnastics,
SKILLS.Identify,
SKILLS.Leadership,
SKILLS.Lore_9Realms,
SKILLS.Lore_Alternative,
SKILLS.Lore_Arcane,
SKILLS.Lore_Arithmancy,
SKILLS.Lore_Divine,
SKILLS.Lore_Geography,
SKILLS.Lore_Nature,
SKILLS.Lore_Nobility,
SKILLS.Lore_Religion,
SKILLS.Lore_Spiritual,
SKILLS.Medical,
SKILLS.Performance,
SKILLS.Ride,
SKILLS.Steal,
SKILLS.Stealth,
SKILLS.Subterfuge,
SKILLS.Swim,
SKILLS.Tailor,
SKILLS.UseContraption,
SKILLS.Wilderness
FROM
(
(
(
(
(
(
(
CHARACTER INNER JOIN RACE_CHARACTER ON
CHARACTER.CharacterID=RACE_CHARACTER.CharacterID
)
LEFT JOIN JOB_CHARACTER ON
CHARACTER.CharacterID=JOB_CHARACTER.CharacterID
)
LEFT JOIN INVENTORY ON
CHARACTER.CharacterID=INVENTORY.CharacterID
)
LEFT JOIN ITEMS ON
ITEMS.ItemID =INVENTORY.ItemID
)
LEFT JOIN JOB ON
JOB.JobID=JOB_CHARACTER.JobID
)
LEFT JOIN SKILLS ON
JOB.JobID=SKILLS.JobID
)
INNER JOIN RACE ON
RACE.RaceID=RACE_CHARACTER.RaceID
)
WHERE
CHARACTER.CharacterID = 1 AND
JOB.JobID = 3 AND
RACE.RaceID = 6
Note that I have changed a couple of the inner joins to left joins because if you use an inner join on a table which is the right of a left join (or on the left of a right join), then you will receive an ambiguous outer joins error.

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.

How to improve the performance of a SQL query even after adding indexes?

I am trying to execute the following sql query but it takes 22 seconds to execute. the number of returned items is 554192. I need to make this faster and have already put indexes in all the tables involved.
SELECT mc.name AS MediaName,
lcc.name AS Country,
i.overridedate AS Date,
oi.rating,
bl1.firstname + ' ' + bl1.surname AS Byline,
b.id BatchNo,
i.numinbatch ItemNumberInBatch,
bah.changedatutc AS BatchDate,
pri.code AS IssueNo,
pri.name AS Issue,
lm.neptunemessageid AS MessageNo,
lmt.name AS MessageType,
bl2.firstname + ' ' + bl2.surname AS SourceFullName,
lst.name AS SourceTypeDesc
FROM profiles P
INNER JOIN profileresults PR
ON P.id = PR.profileid
INNER JOIN items i
ON PR.itemid = I.id
INNER JOIN batches b
ON b.id = i.batchid
INNER JOIN itemorganisations oi
ON i.id = oi.itemid
INNER JOIN lookup_mediachannels mc
ON i.mediachannelid = mc.id
LEFT OUTER JOIN lookup_cities lc
ON lc.id = mc.cityid
LEFT OUTER JOIN lookup_countries lcc
ON lcc.id = mc.countryid
LEFT OUTER JOIN itembylines ib
ON ib.itemid = i.id
LEFT OUTER JOIN bylines bl1
ON bl1.id = ib.bylineid
LEFT OUTER JOIN batchactionhistory bah
ON b.id = bah.batchid
INNER JOIN itemorganisationissues ioi
ON ioi.itemorganisationid = oi.id
INNER JOIN projectissues pri
ON pri.id = ioi.issueid
LEFT OUTER JOIN itemorganisationmessages iom
ON iom.itemorganisationid = oi.id
LEFT OUTER JOIN lookup_messages lm
ON iom.messageid = lm.id
LEFT OUTER JOIN lookup_messagetypes lmt
ON lmt.id = lm.messagetypeid
LEFT OUTER JOIN itemorganisationsources ios
ON ios.itemorganisationid = oi.id
LEFT OUTER JOIN bylines bl2
ON bl2.id = ios.bylineid
LEFT OUTER JOIN lookup_sourcetypes lst
ON lst.id = ios.sourcetypeid
WHERE p.id = #profileID
AND b.statusid IN ( 6, 7 )
AND bah.batchactionid = 6
AND i.statusid = 2
AND i.isrelevant = 1
when looking at the execution plan I can see an step which is costing 42%. Is there any way I could get this to a lower threshold or any way that I can improve the performance of the whole query.
Remove the profiles table as it is not needed and change the WHERE clause to
WHERE PR.profileid = #profileID
You have a left outer join on the batchactionhistory table but also have a condition in your WHERE clause which turns it back into an inner join. Change you code to this:
LEFT OUTER JOIN batchactionhistory bah
ON b.id = bah.batchid
AND bah.batchactionid = 6
You don't need the batches table as it is used to join other tables which could be joined directly and to show the id in you SELECT which is also available in other tables. Make the following changes:
i.batchidid AS BatchNo,
LEFT OUTER JOIN batchactionhistory bah
ON i.batchidid = bah.batchid
Are any of the fields that are used in joins or the WHERE clause from tables that contain large amounts of data but are not indexed. If so try adding an index on at time to the largest table.
Do you need every field in the result - if you could loose one or to you maybe could reduce the number of tables further.
First, if this is not a stored procedure, make it one. That's a lot of text for sql server to complile.
Next, my experience is that "worst practices" are occasionally a good idea. Specifically, I have been able to improve performance by splitting large queries into a couple or three small ones and assembling the results.
If this query is associated with a .net, coldfusion, java, etc application, you might be able to do the split/re-assemble in your application code. If not, a temporary table might come in handy.