Query 1
select student.identifier,
id_tab.reporter_name,
non_id_tab.reporter_name
from student_table student
inner join id_table id_tab on (student.is_NEW = 'Y'
and student.reporter_id = id_tab.reporter_id
and id_tab.name in('name1','name2'))
inner join id_table non_id_tab on (student.non_reporter_id = non_id_tab.reporter_id)
Query 2
select student.identifier,
id_tab.reporter_name,non_id_tab.reporter_name
from student_table student,
id_table id_tab,
id_table non_id_tab
where student.is_NEW = 'Y'
and student.reporter_id = id_tab.reporter_id
and id_tab.name in('name1','name2')
and student.non_reporter_id = non_id_tab.reporter_id
Since these two queries produce exactly same output,I am assuming they are syntactically same(please correct me if I am wrong).
I was wondering whether either of them is more efficient that the other.
Can anyone help me here please?
I would rewrite it as follows, using the ON only for JOIN conditions and moving the filters to a WHERE condition:
...
from student_table student
inner join id_table id_tab on ( student.reporter_id = id_tab.reporter_id )
inner join id_table non_id_tab on (student.non_reporter_id = non_id_tab.reporter_id)
where student.is_NEW = 'Y'
and id_tab.name in('name1','name2')
This should give a more readable query; however, no matter how you write it (the ANSI join is highly preferrable), you should check the explain plans to understand how the query will be executed.
In terms of performance, there should be no difference.
Execution Plans created by the Oracle optimizer do not differ.
In terms of readability, joining tables inside the WHERE clause is an old style (SQL89).
From SQL92 and higher, it is recommended to use the JOIN syntax.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I am having a issue with my INNER join for Oracle. I was hoping you guys could review. Basically the Address table houses addresses of incident and person. I basically need to do a SELECT statement for the incident address then an INNER join to get the persons address as well, for some reason it is not working.
select DISTINCT INCIDENT_PEOPLE_VW.INC_REPORT_NUMBER,trunc((to_number(to_char (offense_status_date,'yyyymmdd'))-to_number(to_char(DOB,'yyyymmdd')))/10000) as AGE,
INCIDENT_PEOPLE_VW.INCIDENT_ID,
OFFENSES.OFFENSE_STATUS_DATE,
INCIDENT_PEOPLE_VW.AGNCY_CD_AGENCY_CODE,
INCIDENT_PEOPLE_VW.STATUS,
INCIDENT_PEOPLE_VW.SEX_SEX_CODE,
INCIDENT_PEOPLE_VW.RACE_RACE_CODE,
INCIDENT_PEOPLE_VW.LNAME,
INCIDENT_PEOPLE_VW.FNAME,
INCIDENT_PEOPLE_VW.DOB,
OFFENSES.REMARKS,
OFFENSE_CODES.OFFENSE_DESC,
P.LONGITUDE,P.LATITUDE,
suspicion_Codes.DESCRIPTION,
P.STREET_NUMBER, P.STREET_NAME,P.STREET_CD_STREET_TYPE_CODE,P.CITY,P.STATE_CD_STATE_CODE,P.ZIP5,
AH.STREET_NUMBER, AH.STREET_NAME,AH.STREET_CD_STREET_TYPE_CODE,AH.CITY,AH.STATE_CD_STATE_CODE,AH.ZIP5
from
INCIDENT_PEOPLE_VW,
OFFICER_INCIDENTS,OFFENSES,OFFENSE_CODES, OFFICERS,
ADDRESSES P, INCIDENT_ADDRESSES,offender_suspicions,suspicion_Codes,person_addresses D
INNER JOIN ADDRESSES ah
ON D.address_id= ah.address_ID
where OFFICER_INCIDENTS.INC_INCIDENT_ID=INCIDENT_PEOPLE_VW.INCIDENT_ID
AND INCIDENT_PEOPLE_VW.INCIDENT_ID=INCIDENT_ADDRESSES.INCIDENT_ID
AND INCIDENT_ADDRESSES.ADDRESS_ID=P.ADDRESS_ID
AND INCIDENT_PEOPLE_VW.INCIDENT_ID = OFFENSES.INC_INCIDENT_ID
AND INCIDENT_PEOPLE_VW.INCIDENT_ID = OFFENDER_SUSPICIONS.OFFNSE_INC_INCIDENT_ID
AND OFFENDER_SUSPICIONS.SUSPICN_CD_SUSPICION_CODE =SUSPICION_CODES.SUSPICION_CODE
AND OFFENSES.OFFNS_CD_OFFENSE_CODE = OFFENSE_CODES.OFFENSE_CODE
AND OFFICER_INCIDENTS.OFF1_OFFICER_ID = OFFICERS.OFFICER_ID
and OFFICER_INCIDENTS.ORC_ROLE_CODE='R'
and incident_people_vw.status='A'
and INCIDENT_PEOPLE_VW.ROLE_ROLE_TYPE IN ('A','S')
AND trunc((to_number(to_char(offense_status_date,'yyyymmdd'))-to_number(to_char (DOB,'yyyymmdd')))/10000) <= 17
The exact reason for your query to fail is the one #Politank-Z wrote you ...
You are mixing ANSI syntax of joins with the "old" syntax with join predicates in the WHERE clause.
If you used the ANSI syntax consistently, you would easily spot the problem, being that your person_addresses table join lacks the actual join predicate and, as such, your DB server is doing a cartesian product instead, effectively devouring all of your temporary tablespace.
Here you are, a slight iterative revamp of your query ...
Iteration 1 - introducing basic indentation and remaking all WHERE-clause join predicates to ANSI joins
select distinct
INCIDENT_PEOPLE_VW.INC_REPORT_NUMBER,
trunc((to_number(to_char(offense_status_date,'yyyymmdd')) - to_number(to_char(DOB,'yyyymmdd')))/10000) as AGE,
INCIDENT_PEOPLE_VW.INCIDENT_ID,
OFFENSES.OFFENSE_STATUS_DATE,
INCIDENT_PEOPLE_VW.AGNCY_CD_AGENCY_CODE,
INCIDENT_PEOPLE_VW.STATUS,
INCIDENT_PEOPLE_VW.SEX_SEX_CODE,
INCIDENT_PEOPLE_VW.RACE_RACE_CODE,
INCIDENT_PEOPLE_VW.LNAME,
INCIDENT_PEOPLE_VW.FNAME,
INCIDENT_PEOPLE_VW.DOB,
OFFENSES.REMARKS,
OFFENSE_CODES.OFFENSE_DESC,
P.LONGITUDE,P.LATITUDE,
suspicion_Codes.DESCRIPTION,
P.STREET_NUMBER, P.STREET_NAME,P.STREET_CD_STREET_TYPE_CODE,P.CITY,P.STATE_CD_STATE_CODE,P.ZIP5,
AH.STREET_NUMBER, AH.STREET_NAME,AH.STREET_CD_STREET_TYPE_CODE,AH.CITY,AH.STATE_CD_STATE_CODE,AH.ZIP5
from
INCIDENT_PEOPLE_VW
join OFFICER_INCIDENTS
on OFFICER_INCIDENTS.INC_INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join OFFENSES
on OFFENSES.INC_INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join OFFENSE_CODES
on OFFENSE_CODES.OFFENSE_CODE = OFFENSES.OFFNS_CD_OFFENSE_CODE
join OFFICERS
on OFFICERS.OFFICER_ID = OFFICER_INCIDENTS.OFF1_OFFICER_ID
join INCIDENT_ADDRESSES
on INCIDENT_ADDRESSES.INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join ADDRESSES P
on P.ADDRESS_ID = INCIDENT_ADDRESSES.ADDRESS_ID
join offender_suspicions
on OFFENDER_SUSPICIONS.OFFNSE_INC_INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join suspicion_Codes
on SUSPICION_CODES.SUSPICION_CODE = OFFENDER_SUSPICIONS.SUSPICN_CD_SUSPICION_CODE
person_addresses D,
INNER JOIN ADDRESSES ah
ON ah.address_ID = D.address_id
where
OFFICER_INCIDENTS.ORC_ROLE_CODE = 'R' and
incident_people_vw.status = 'A' and
INCIDENT_PEOPLE_VW.ROLE_ROLE_TYPE IN ('A','S') and
trunc((to_number(to_char(offense_status_date,'yyyymmdd'))-to_number(to_char(DOB,'yyyymmdd')))/10000) <= 17
;
Iteration 2 - identifying mistakenly forgotten cartesian products (i.e. joins without a join predicate, because when you put all your join predicates to your WHERE clause, you EASILY forget some)
In this case it's the PERSON_ADDRESSES table.
Iteration 3 - fixing the missing join predicates
select distinct
INCIDENT_PEOPLE_VW.INC_REPORT_NUMBER,
trunc((to_number(to_char(offense_status_date,'yyyymmdd')) - to_number(to_char(DOB,'yyyymmdd')))/10000) as AGE,
INCIDENT_PEOPLE_VW.INCIDENT_ID,
OFFENSES.OFFENSE_STATUS_DATE,
INCIDENT_PEOPLE_VW.AGNCY_CD_AGENCY_CODE,
INCIDENT_PEOPLE_VW.STATUS,
INCIDENT_PEOPLE_VW.SEX_SEX_CODE,
INCIDENT_PEOPLE_VW.RACE_RACE_CODE,
INCIDENT_PEOPLE_VW.LNAME,
INCIDENT_PEOPLE_VW.FNAME,
INCIDENT_PEOPLE_VW.DOB,
OFFENSES.REMARKS,
OFFENSE_CODES.OFFENSE_DESC,
P.LONGITUDE,P.LATITUDE,
suspicion_Codes.DESCRIPTION,
P.STREET_NUMBER, P.STREET_NAME,P.STREET_CD_STREET_TYPE_CODE,P.CITY,P.STATE_CD_STATE_CODE,P.ZIP5,
AH.STREET_NUMBER, AH.STREET_NAME,AH.STREET_CD_STREET_TYPE_CODE,AH.CITY,AH.STATE_CD_STATE_CODE,AH.ZIP5
from
INCIDENT_PEOPLE_VW
join OFFICER_INCIDENTS
on OFFICER_INCIDENTS.INC_INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join OFFENSES
on OFFENSES.INC_INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join OFFENSE_CODES
on OFFENSE_CODES.OFFENSE_CODE = OFFENSES.OFFNS_CD_OFFENSE_CODE
join OFFICERS
on OFFICERS.OFFICER_ID = OFFICER_INCIDENTS.OFF1_OFFICER_ID
join INCIDENT_ADDRESSES
on INCIDENT_ADDRESSES.INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join ADDRESSES P
on P.ADDRESS_ID = INCIDENT_ADDRESSES.ADDRESS_ID
join offender_suspicions
on OFFENDER_SUSPICIONS.OFFNSE_INC_INCIDENT_ID = INCIDENT_PEOPLE_VW.INCIDENT_ID
join suspicion_Codes
on SUSPICION_CODES.SUSPICION_CODE = OFFENDER_SUSPICIONS.SUSPICN_CD_SUSPICION_CODE
join person_addresses D
on D.<some column> = <some table from the above ones>.<some column from the table>
JOIN ADDRESSES ah
ON AH.address_id = D.address_id
where
OFFICER_INCIDENTS.ORC_ROLE_CODE = 'R' and
incident_people_vw.status = 'A' and
INCIDENT_PEOPLE_VW.ROLE_ROLE_TYPE IN ('A','S') and
trunc((to_number(to_char(offense_status_date,'yyyymmdd'))-to_number(to_char(DOB,'yyyymmdd')))/10000) <= 17
;
Iteration 4 - fixing the wonderfully strange age calculation, introducing consistent formatting and consistent table aliases to improve readability
select distinct
IP.incident_id, IP.inc_report_number,
-- trunc((to_number(to_char(OFS.offense_status_date,'yyyymmdd')) - to_number(to_char(IP.dob,'yyyymmdd')))/10000) as age,
months_between(OFS.offense_status_date, IP.dob) / 12 as age
OFS.offense_status_date,
IP.agncy_cd_agency_code, IP.status, IP.sex_sex_code, IP.race_race_code, IP.lname, IP.fname, IP.dob,
OFS.remarks,
OC.offense_desc,
AIA.longitude, AIA.latitude,
SC.description,
AIA.street_number, AIA.street_name, AIA.street_cd_street_type_code, AIA.city, AIA.state_cd_state_code, AIA.zip5,
PAA.street_number, PAA.street_name, PAA.street_cd_street_type_code, PAA.city, PAA.state_cd_state_code, PAA.zip5
from
incident_people_vw IP
join officer_incidents OI
on OI.inc_incident_id = IP.incident_id
join offenses OFS
on OFS.inc_incident_id = IP.incident_id
join offense_codes OC
on OC.offense_code = OFS.offns_cd_offense_code
join officers O
on O.officer_id = OI.off1_officer_id
join incident_addresses IA
on IA.incident_id = IP.incident_id
join addresses AIA
on AIA.address_id = IA.address_id
join offender_suspicions OS
on OS.offnse_inc_incident_id = IP.incident_id
join suspicion_codes SC
on SC.suspicion_code = OS.suspicn_cd_suspicion_code
join person_addresses PA
on PA.<some column> = <some table alias from the above ones>.<some column from the table>
join addresses PAA
on PAA.address_id = PA.address_id
where
OI.orc_role_code = 'R' and
IP.status = 'A' and
IP.role_role_type in ('A','S') and
-- trunc((to_number(to_char(OFS.offense_status_date,'yyyymmdd')) - to_number(to_char(IP.dob,'yyyymmdd')))/10000) <= 17
months_between(OFS.offense_status_date, IP.dob) / 12 <= 17
;
Enjoy. And from now on always use the ANSI join syntax.
This question already has answers here:
C# Null coalesce with LINQ
(4 answers)
Closed 4 years ago.
This is my SQL query:
select
S.student_No,
coalesce(P.Name,'0'),
P.Surname
from
Person as P
join
Student as S
on P.Id = S.Person_Id
I want to convert it LINQ , i did it except coalesce function,
from P in cbu.PERSON
join S in cbu.STUDENT on P.ID equals S.PERSON_ID
select new
{
S.Stundent_No,
P.Name,
P.Surname,
};
how can I use coalesce in this linq query
P.Name ?? "0". C# has the coalesce operator built-in. Even if you didn't know that, you could use the ?: operator.
The join is not necessary, btw. You can just write P.Student.Stundent_No (or whatever the properties are called).
This question already has an answer here:
In explicit LINQ-to-SQL (C#) does order matter?
(1 answer)
Closed 8 years ago.
I have this linq Query in a C# project
var query = from p in db.Posts
join a in db.Author on p.Author equals a
join u in db.Users on p.PostedBy equals u
where p.IsActive.Equals(true)
orderby p.PostedDate descending
select new ViewModel
{
...
};
If I move where p.IsActive.Equals(true) near from p in db.Posts, like
var query = from p in db.Posts
where p.IsActive.Equals(true) //Moved
join a in db.Author on p.Author equals a
join u in db.Users on p.PostedBy equals u
orderby p.PostedDate descending
select new ViewModel
{
...
};
will it make any difference to the performance of the query?
I'm not sure that it will work if you'll do it, but if you are using it against a SQL database it should not make any difference. Both queries will be translated to the SQL like this one:
SELECT ...
FROM Posts INNER JOIN Author ON ... INNER JOIN Users ON ...
WHERE Posts.IsActive = true
...
Concerning performance, I would strongly suggest to put
the joins before any where.
The reason is, that the joins already make a smaller set
(the p is selected from Posts and then only
the matching rows from Author and Users are taken.
In opposite, if you have a where near the beginning
a caresian (big) product is calculated and then filtered.
(in your special case, only one table is affected, but
the query may be altered sometime and nobody knows then
why it is slow).
Please read this SO Why is LINQ join so much faster than LINQ where
And more on your special case: as this is affecting a database,
the resulting SQL statements should be the same in both queries.
Have a look at it!
This question follows on from a question I asked yesterday about why using the join query on my Entities produced horrendously complicated SQL. It seemed that performing a query like this:
var query = from ev in genesisContext.Events
join pe in genesisContext.People_Event_Link
on ev equals pe.Event
where pe.P_ID == key
select ev;
Produced the horrible SQL that took 18 seconds to run on the database, whereas joining the entities through a where clause (sort of like pre-ANSI SQL syntax) took less than a second to run and produced the same result
var query = from pe in genesisContext.People_Event_Link
from ev in genesisContext.Events
where pe.P_ID == key && pe.Event == ev
select ev;
I've googled all over but still don't understand why the second is produces different SQL to the first. Can someone please explain the difference to me? When should I use the join keyword
This is the SQL that was produced when I used Join in my query and took 18 seconds to run:
SELECT
1 AS [C1],
[Extent1].[E_ID] AS [E_ID],
[Extent1].[E_START_DATE] AS [E_START_DATE],
[Extent1].[E_END_DATE] AS [E_END_DATE],
[Extent1].[E_COMMENTS] AS [E_COMMENTS],
[Extent1].[E_DATE_ADDED] AS [E_DATE_ADDED],
[Extent1].[E_RECORDED_BY] AS [E_RECORDED_BY],
[Extent1].[E_DATE_UPDATED] AS [E_DATE_UPDATED],
[Extent1].[E_UPDATED_BY] AS [E_UPDATED_BY],
[Extent1].[ET_ID] AS [ET_ID],
[Extent1].[L_ID] AS [L_ID]
FROM [dbo].[Events] AS [Extent1]
INNER JOIN [dbo].[People_Event_Link] AS [Extent2] ON EXISTS (SELECT
1 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
LEFT OUTER JOIN (SELECT
[Extent3].[E_ID] AS [E_ID]
FROM [dbo].[Events] AS [Extent3]
WHERE [Extent2].[E_ID] = [Extent3].[E_ID] ) AS [Project1] ON 1 = 1
LEFT OUTER JOIN (SELECT
[Extent4].[E_ID] AS [E_ID]
FROM [dbo].[Events] AS [Extent4]
WHERE [Extent2].[E_ID] = [Extent4].[E_ID] ) AS [Project2] ON 1 = 1
WHERE ([Extent1].[E_ID] = [Project1].[E_ID]) OR (([Extent1].[E_ID] IS NULL) AND ([Project2].[E_ID] IS NULL))
)
WHERE [Extent2].[P_ID] = 291
This is the SQL that was produce using the ANSI Style syntax (and is fairly close to what I would write if I were writing the SQL myself):
SELECT * FROM Events AS E INNER JOIN People_Event_Link AS PE ON E.E_ID=PE.E_ID INNER JOIN PEOPLE AS P ON P.P_ID=PE.P_ID
WHERE P.P_ID = 291
Neither of the above queries are entirely "correct." In EF, it is generally correct to use the relationship properties in lieu of either of the above. For example, if you had a Person object with a one to many relationship to PhoneNumbers in a property called Person.PhoneNumbers, you could write:
var q = from p in Context.Person
from pn in p.PhoneNumbers
select pn;
The EF will build the join for you.
In terms of the question above, the reason the generated SQL is different is because the expression trees are different, even though they produce equivalent results. Expression trees are mapped to SQL, and you of course know that you can write different SQL which produces the same results but with different performance. The mapping is designed to produce decent SQL when you write a farily "conventional" EF query.
But the mapping is not so smart as to take a very unconventional query and optimize it. In your first query, you state that the objects must be equivalent. In the second, you state that the ID property must be equivalent. My sample query above says "just get the details for this one record." The EF is designed to work with the way I show, principally, but also handles scalar equivalence well.