Convert inner join to SQL Subquery - sql

my SQL Query is as follow:
i m using inner join in that query...
i want to modify that into subquery
select distinct Auditdata.ID,
ns.ProviderMaster_ID as CDRComment
from Auditdata AuditData
inner join AuditMaster am
on am.ID = AuditData.AuditMaster_ID
inner join HomeCircleMaster hcm
on hcm.Ori_CircleMaster_ID = am.CircleMaster_ID and hcm.Ori_ServiceTypeMaster_ID = 1 and hcm.Dest_ServiceTypeMaster_ID = 1 inner join AuditTaggingMaster atm
on atm.AuditMaster_ID = am.ID
inner join NoSeriesMaster ns on
( ns.CircleMaster_ID = am.CircleMaster_ID or ns.CircleMaster_ID = hcm.Dest_CircleMaster_ID) and ns.ProviderMaster_ID <> am.ProviderMaster_ID and ns.ServiceTypeMaster_ID = 1
inner join ProviderMaster_CallTypeMaster pm_ctm
on pm_ctm.ProviderMaster_ID = am.ProviderMaster_ID and pm_ctm.CallTypeMaster_ID = 101 and pm_ctm.CallTypeTagValue =AuditData.CallTypeTag INNER JOIN NoSeriesMaster_Prefix PD ON AuditData.CallTo like PD.PrefixNo + '%' AND AuditData.calltolen = PD.PrefixLen + PD.AfterPrefixLen AND PD.PrefixNo + ns.NoSeries = LEFT(AuditData.CallTo, NoSeriesLen + PD.PrefixLen) where AuditData.TATCallType is null and AuditData.AuditMaster_ID = 74 AND PD.PrefixType = 'SMS'
Please help me
thanx

I would try to post the query beautified. Otherwise it is hard to help. Try to explain also what are you trying to do so. There are 6 Inner joins. Which one would you like to change.
Anyway. Your question seems to be an quite similar to This one. Please don't post questions twice.
Apart from that It seems that you are trying to optimize this query. Why don't you just ask who to make it faster? In my humble opinion using subquerys will make everything worse.
If you need help optimizing we would need more information like the table structure, indexes, number of rows, etc...
select distinct Auditdata.ID,
ns.ProviderMaster_ID as CDRComment
from Auditdata AuditData
inner join AuditMaster am on am.ID = AuditData.AuditMaster_ID
inner join HomeCircleMaster hcm on hcm.Ori_CircleMaster_ID = am.CircleMaster_ID
and hcm.Ori_ServiceTypeMaster_ID = 1
and hcm.Dest_ServiceTypeMaster_ID = 1
inner join AuditTaggingMaster atm on atm.AuditMaster_ID = am.ID
inner join NoSeriesMaster ns on ( ns.CircleMaster_ID = am.CircleMaster_ID
or ns.CircleMaster_ID = hcm.Dest_CircleMaster_ID)
and ns.ProviderMaster_ID <> am.ProviderMaster_ID
and ns.ServiceTypeMaster_ID = 1
inner join ProviderMaster_CallTypeMaster pm_ctm on pm_ctm.ProviderMaster_ID = am.ProviderMaster_ID
and pm_ctm.CallTypeMaster_ID = 101
and pm_ctm.CallTypeTagValue =AuditData.CallTypeTag
INNER JOIN NoSeriesMaster_Prefix PD ON AuditData.CallTo like PD.PrefixNo + '%'
AND AuditData.calltolen = PD.PrefixLen + PD.AfterPrefixLen
AND PD.PrefixNo + ns.NoSeries = LEFT(AuditData.CallTo, NoSeriesLen + PD.PrefixLen)
where AuditData.TATCallType is null
and AuditData.AuditMaster_ID = 74
AND PD.PrefixType = 'SMS

Related

Access Query - Group by and Max

I have been working on this for a few hours now and just can not figure it out.
How would I go about sorting this query by enco_id and only having the max of each clpr_id show up. for example:
Here is my MSAccess Sql Code
SELECT dbo_Client.med_rec_no, dbo_Encounter.episode_number, dbo_client_program.enco_id, dbo_client_program.clpr_id, dbo_client_program.prle_id, dbo_PROGRAM_LEVEL.prle_name, dbo_Client.fname, dbo_Client.lname, dbo_DISCHARGE_STATUS.dist_name, DS2.dist_name
FROM (((((dbo_Client INNER JOIN dbo_Encounter ON dbo_Client.client_id = dbo_Encounter.client_id) INNER JOIN dbo_Episode_info ON dbo_Encounter.enco_id = dbo_Episode_info.enco_id) INNER JOIN dbo_DISCHARGE_STATUS ON dbo_Episode_info.dist_id = dbo_DISCHARGE_STATUS.dist_id) INNER JOIN dbo_client_program ON dbo_Encounter.enco_id = dbo_client_program.enco_id) INNER JOIN dbo_DISCHARGE_STATUS AS DS2 ON dbo_client_program.dist_id = DS2.dist_id) INNER JOIN dbo_PROGRAM_LEVEL ON dbo_client_program.prle_id = dbo_PROGRAM_LEVEL.prle_id;
Also here is what my query looks like
EDIT:
This is the code I am trying to use now and it still is not working
SELECT dbo_Client.client_id, dbo_Client.med_rec_no, dbo_Encounter.episode_number, dbo_Encounter.start_date, dbo_Encounter.end_date, dbo_client_program.clpr_id, dbo_client_program.enco_id, dbo_PROGRAM_LEVEL.prle_name, dbo_Client.fname, dbo_Client.lname, dbo_DISCHARGE_STATUS.dist_name, DS2.dist_name
FROM (((((dbo_Client INNER JOIN dbo_Encounter ON dbo_Client.client_id = dbo_Encounter.client_id) INNER JOIN dbo_Episode_info ON dbo_Encounter.enco_id = dbo_Episode_info.enco_id) INNER JOIN dbo_DISCHARGE_STATUS ON dbo_Episode_info.dist_id = dbo_DISCHARGE_STATUS.dist_id) INNER JOIN dbo_client_program ON dbo_Encounter.enco_id = dbo_client_program.enco_id) INNER JOIN dbo_DISCHARGE_STATUS AS DS2 ON dbo_client_program.dist_id = DS2.dist_id) INNER JOIN dbo_PROGRAM_LEVEL ON dbo_client_program.prle_id = dbo_PROGRAM_LEVEL.prle_id
WHERE dbo_client_program.clpr_id IN
(SELECT TOP 1 clpr_id FROM dbo_client_program as New
WHERE New.clpr_id = dbo_client_program.clpr_id
ORDER by dbo_client_program.clpr_id DESC) AND (dbo_DISCHARGE_STATUS.dist_name <> DS2.dist_name) AND dbo_Encounter.start_date > #1/1/2020# AND dbo_Encounter.end_date > #1/1/2020#
ORDER BY dbo_Encounter.episode_number;
As you are still understanding the aggregate queries my suggestion is:
1-Create a query where you group by all fields and max(clpr_id). Save this as "Query1"
2-Create another query based on "Query1" and sort by "enco_id "

SQL Subquery - Repeat Where Clause?

I know this is a 101 question, but do I need to repeat the Where clause in the main query in the sub-query below? It appears to give me the same either way, but is it even needed?
FROM account a
LEFT JOIN account pa ON a.parentaccountid = pa.accountid
JOIN customeraddress ca ON a.accountid = ca.parentid
JOIN optionsetmetadata osm ON osm.entityname = 'customeraddress'
AND osm.optionsetname = 'addresstypecode'
AND ca.addresstypecode = osm.[option]
LEFT JOIN sik_warehouse w ON a.sik_warehouseid = w.sik_warehouseid
LEFT JOIN sik_deliverymethods dm ON a.sik_deliverymethodid = dm.sik_deliverymethodsid
WHERE a.accountnumber IN ('58398',
'4350',
'5076',
'4310',
'15847')
AND Addresstypecode = 2
AND ca.jms_status = 100000000
AND ca.addressnumber > (
SELECT TOP 1 ca_sub1.addressnumber
FROM customeraddress ca_sub1
JOIN account a_sub1 ON ca_sub1.parentid = a_sub1.accountid
AND ca_sub1.addressnumber > 2
order by ca_sub1.addressnumber ASC
add inline view if you want to put multiple where condition.

JOIN syntax and order for multiple tables

SQL Gurus,
I have a query that uses the "old" style of join syntax as follows using 7 tables (table and column names changed to protect the innocent), as shown below:
SELECT v1_col, p1_col
FROM p1_tbl, p_tbl, p2_tbl, p3_tbl, v1_tbl, v2_tbl, v3_tbl
WHERE p1_code = 1
AND v1_code = 1
AND p1_date >= v1_date
AND p_uid = p1_uid
AND p2_uid = p1_uid AND p2_id = v2_id
AND p3_uid = p1_uid AND p3_id = v3_id
AND v2_uid = v1_uid
AND v3_uid = v1_uid
The query works just fine and produces the results it is supposed to, but as an academic exercise, I tried to rewrite the query using the more standard JOIN syntax, for example, below is one version I tried:
SELECT V1.v1_col, P1.p1_col
FROM p1_tbl P1, v1_tbl V1
JOIN p_tbl P ON ( P.p_uid = P1.p1_uid )
JOIN p2_tbl P2 ON ( P2.p2_uid = P1.p1_uid AND P2.p2_id = V2.v2_id )
JOIN p3_tbl P3 ON ( P3.p3_uid = P1.p1_uid AND P3.p3_id = V3.v3_id )
JOIN v2_tbl V2 ON ( V2.v2_uid = V1.v1_uid )
JOIN v3_tbl V3 ON ( V3.v3_uid = V1.v1_uid )
WHERE P1.p1_code = 1
AND V1.v1_code = 1
AND P1.p1_date >= V1.v1_date
But, no matter how I arrange the JOINs (using MS SQL 2008 R2), I keep running into the error:
The Multi-part identifier "col-name" could not be bound,
where "col-name" varies depending on the order of the JOINs I am attempting...
Does anyone have any good examples on how use the JOIN syntax with this number of tables??
Thanks in advance!
When you use JOIN-syntax you can only access columns from tables in your current join or previous joins. In fact it's easier to write the old syntax, but it's more error-prone, e.g. you can easily forget a join-condition.
This should be what you want.
SELECT v1_col, p1_col
FROM p1_tbl
JOIN v1_tbl ON p1_date >= v1_date
JOIN v2_tbl ON v2_uid = v1_uid
JOIN v3_tbl ON v3_uid = v1_uid
JOIN p_tbl ON p_uid = p1_uid
JOIN p2_tbl ON p2_uid = p1_uid AND p2_id = v2_id
JOIN p3_tbl ON p3_uid = p1_uid AND p3_id = v3_id
WHERE p1_code = 1
AND v1_code = 1
You are not naming the tables in your join such that it doesn't know which column is from which table. Try something like:
SELECT a.v1_col, b.p1_col
FROM p1_tbl b
JOIN p_tbl a ON b.p_uid = a.p1_uid
WHERE b.p1_code = 1
From your query above, I am assuming a naming convention of p2_uid comes from p2_tbl. Below id my best interpretation of WHERE joins to using INNER joins.
SELECT
v1_col, p1_col
FROM
p1_tbl
INNER JOIN p1_tbl
ON p1_tbl.p1_date >= v1_tbl.v1_date
INNER JOIN p_tbl
ON p_tbl.p_uid = p1_tbl.p1_uid
INNER JOIN p2_tbl
ON p2_tbl.p2_uid = p1_tbl.p1_uid
INNER JOIN v2_tbl
ON p2_tbl.p2_id = v2_tbl.v2_id
INNER JOIN p3_tbl
ON p3_tbl.p3_uid = p1_tbl.p1_uid
INNER JOIN v3_tbl
ON p3_tbl.p3_id = v3_tbl.v3_id
INNER JOIN v1_tbl
ON v1_tbl.v1_uid = v2_tbl.v2_uid
AND v1_tbl.v1_uid = v3_tbl.v2_uid
WHERE
p1_code = 1
AND
v1_code = 1
Some general points I have found useful in SQL statements with many joins.
Always fully qualify the names. I.e dont use ID , rahter use
TableName.ID
Dont use aliases unless there is meaning. (I.e. joining a table to
its self where aliasing is needed.)

How to use ISNULL in a Query within a query?

My SQL Query below is now Returning the RoomsAvailable field correctly except when theres 0 rooms taken, in which the SQL command subtracts number_of_rooms with NULL and outputs NULL to the Column. I have tried numerous ISNULL variations and found that it doesnt work; anyone know how I should be doing this?
SQL :
SELECT
Hotel_2.hotel_code,
Hotel_2.hotel_country,
Room_type_rates_2.room_type_code,
Room_type_rates_2.number_of_rooms,
Types_2.room_type,
Room_type_rates_2.rates,
Room_type_rates_2.number_of_rooms -
(SELECT
DISTINCT (SELECT
COUNT(dbo.Hotel.hotel_code) AS RoomsTake
FROM
dbo.Hotel
INNER JOIN dbo.Hotel_Reservation
ON dbo.Hotel.hotel_code = dbo.Hotel_Reservation.hotel_code
INNER JOIN dbo.Room_type_rates
ON dbo.Hotel.hotel_code = dbo.Room_type_rates.hotel_code
INNER JOIN dbo.Types
ON dbo.Hotel_Reservation.room_type_code = dbo.Types.room_type_code
AND dbo.Room_type_rates.room_type_code = dbo.Types.room_type_code
WHERE
(dbo.Room_type_rates.room_type_code = Room_type_rates_1.room_type_code)
AND (dbo.Hotel.hotel_code = Hotel_1.hotel_code)
AND (dbo.Hotel_Reservation.checkin_date >= Hotel_Reservation_1.checkin_date)
AND (dbo.Hotel_Reservation.checkout_date <= Hotel_Reservation_1.checkout_date)
) AS RoomsTaken
FROM
dbo.Hotel AS Hotel_1
INNER JOIN dbo.Hotel_Reservation AS Hotel_Reservation_1
ON Hotel_1.hotel_code = Hotel_Reservation_1.hotel_code
INNER JOIN dbo.Room_type_rates AS Room_type_rates_1
ON Hotel_1.hotel_code = Room_type_rates_1.hotel_code
INNER JOIN dbo.Types AS Types_1
ON Hotel_Reservation_1.room_type_code = Types_1.room_type_code
AND Room_type_rates_1.room_type_code = Types_1.room_type_code
WHERE
(Hotel_Reservation_1.checkin_date >= '11/19/2011')
AND (Hotel_Reservation_1.checkout_date <= '12/01/2011')
AND (Hotel_1.hotel_country = 'Adelaide')
AND (Types_1.room_type_code = Types_2.room_type_code)
) AS RoomsAvailable
FROM
dbo.Hotel AS Hotel_2
INNER JOIN dbo.Room_type_rates AS Room_type_rates_2
ON Hotel_2.hotel_code = Room_type_rates_2.hotel_code
INNER JOIN dbo.Types AS Types_2
ON Room_type_rates_2.room_type_code = Types_2.room_type_code
Current Output :
ADL20 Adelaide CPL 6 Couple Suite 514.0000 3
ADL20 Adelaide FYU 3 Family Suite 533.0000 2
ADL20 Adelaide KNG 2 King's Bedroom 556.0000 NULL
Do you mean this?:
...ISNULL(COUNT(dbo.Hotel.*),0)...
Or is the problem that you're getting NULL at all? In that case I would suspect your JOINs may have a problem.
You can wrap an ISNULL around any nested subquery or value.

Making join condition more exclusive causes query to hang

Sorry for the wall of SQL, but I am having some problems with the query below. It seems to never finish executing (it runs for a few minutes, then I kill it). The weird thing is that if I change the join condition for the StudentTestsPre table from TestInstances.fkSchoolYearID = (TestInstancesPre.fkSchoolYearID + 1) to TestInstances.fkSchoolYearID > TestInstancesPre.fkSchoolYearID, then the query returns instantly. How could using a more exclusive join condition cause my query to hang? Seems like that should make the query faster, if anything.
Any ideas?
SELECT *
FROM TestInstances
INNER JOIN StudentTests on StudentTests.fkTestInstanceID = TestInstances.pkTestInstanceID
AND StudentTests.pkStudentTestID IN (SELECT * FROM #tempTests)
INNER JOIN TestInstances TestInstancesPre ON TestInstances.fkSchoolYearID = (TestInstancesPre.fkSchoolYearID + 1)
AND TestInstancesPre.fkTestTypeID = 1 AND TestInstances.fkTestTypeID = 1
INNER JOIN StudentTests StudentTestsPre on StudentTestsPre.fkTestInstanceID = TestInstancesPre.pkTestInstanceID
AND StudentTests.fkStudentID = StudentTestsPre.fkStudentID
INNER JOIN StudentScores_Subject s ON s.fkStudentTestID = StudentTests.pkStudentTestID
AND s.fkTest_SubjectID IN (SELECT pkTestSubjectID FROM MM_Test_Subjects WHERE fkCSTStrandID IN (SELECT number FROM itot(#strAcceptableStrands, N',')) AND fkTestTypeID = 1)
AND s.fkScoreTypeID = 3
INNER JOIN StudentScores_Subject sPre ON sPre.fkStudentTestID = StudentTestsPre.pkStudentTestID
AND sPre.fkTest_SubjectID IN (SELECT pkTestSubjectID FROM MM_Test_Subjects WHERE fkCSTStrandID IN (SELECT number FROM itot(#strAcceptableStrands, N',')) AND fkTestTypeID = 1)
AND sPre.fkScoreTypeID = 3
INNER JOIN MM_Test_PL_SS_Ranges r ON r.fkTest_SubjectID = s.fkTest_SubjectID
AND r.fkSchoolYearID = TestInstances.fkSchoolYearID
AND r.fkTestTypeID = TestInstances.fkTestTypeID
AND (r.fkGradeID = StudentTests.fkGradeID OR r.fkGradeID = 99)
INNER JOIN MM_Test_PL_SS_Ranges rPre ON rPre.fkTest_SubjectID = sPre.fkTest_SubjectID
AND rPre.fkSchoolYearID = TestInstancesPre.fkSchoolYearID
AND rPre.fkTestTypeID = TestInstancesPre.fkTestTypeID
AND (rPre.fkGradeID = StudentTestsPre.fkGradeID OR rPre.fkGradeID = 99)
INNER JOIN StudentScores_Subject s2 ON s2.fkStudentTestID = StudentTests.pkStudentTestID
AND s2.fkTest_SubjectID = s.fkTest_SubjectID
AND s2.fkScoreTypeID = 2
INNER JOIN StudentScores_Subject sPre2 ON sPre2.fkStudentTestID = StudentTestsPre.pkStudentTestID
AND sPre2.fkTest_SubjectID = sPre.fkTest_SubjectID
AND sPre2.fkScoreTypeID = 2
INNER JOIN Students on Students.pkStudentID = StudentTests.fkStudentID
thanks for the help!
For SO, here's the above script with alternative formatting & short aliases:
SELECT *
FROM TestInstances
INNER JOIN StudentTests st
ON st.fkTestInstanceID = ti.pkTestInstanceID
AND st.pkStudentTestID IN (SELECT * FROM #tempTests)
INNER JOIN TestInstances tiPre
ON ti.fkSchoolYearID = (tiPre.fkSchoolYearID + 1)
AND tiPre.fkTestTypeID = 1 AND ti.fkTestTypeID = 1
INNER JOIN StudentTests stPre
ON stPre.fkTestInstanceID = tiPre.pkTestInstanceID
AND st.fkStudentID = stPre.fkStudentID
INNER JOIN StudentScores_Subject s
ON s.fkStudentTestID = st.pkStudentTestID
AND s.fkTest_SubjectID IN (
SELECT pkTestSubjectID
FROM MM_Test_Subjects
WHERE fkCSTStrandID IN (
SELECT number FROM itot(#strAcceptableStrands, N','))
AND fkTestTypeID = 1)
AND s.fkScoreTypeID = 3
INNER JOIN StudentScores_Subject sPre
ON sPre.fkStudentTestID = stPre.pkStudentTestID
AND sPre.fkTest_SubjectID IN (
SELECT pkTestSubjectID
FROM MM_Test_Subjects
WHERE fkCSTStrandID IN (
SELECT number FROM itot(#strAcceptableStrands, N','))
AND fkTestTypeID = 1)
AND sPre.fkScoreTypeID = 3
INNER JOIN MM_Test_PL_SS_Ranges r
ON r.fkTest_SubjectID = s.fkTest_SubjectID
AND r.fkSchoolYearID = ti.fkSchoolYearID
AND r.fkTestTypeID = ti.fkTestTypeID
AND (r.fkGradeID = st.fkGradeID OR r.fkGradeID = 99)
INNER JOIN MM_Test_PL_SS_Ranges rPre
ON rPre.fkTest_SubjectID = sPre.fkTest_SubjectID
AND rPre.fkSchoolYearID = tiPre.fkSchoolYearID
AND rPre.fkTestTypeID = tiPre.fkTestTypeID
AND (rPre.fkGradeID = stPre.fkGradeID OR rPre.fkGradeID = 99)
INNER JOIN StudentScores_Subject s2
ON s2.fkStudentTestID = st.pkStudentTestID
AND s2.fkTest_SubjectID = s.fkTest_SubjectID
AND s2.fkScoreTypeID = 2
INNER JOIN StudentScores_Subject sPre2
ON sPre2.fkStudentTestID = stPre.pkStudentTestID
AND sPre2.fkTest_SubjectID = sPre.fkTest_SubjectID
AND sPre2.fkScoreTypeID = 2
INNER JOIN Students
ON Students.pkStudentID = st.fkStudentID
Take a look at your execution plan. My guess is that doing the calculation in the join aka (TestInstancesPre.fkSchoolYearID + 1) is causing indexes not be used correctly. An easy way to test this would be to change your join to:
TestInstances.fkSchoolYearID = TestInstancesPre.fkSchoolYearID
I have seen performance go way down when doing funky stuff in a join. Things like:
ON t1.column1 = ISNULL(t2.myColumn, 1)
I believe this is because the query becomes non-sargable. Take a look at this SO post for more details on that.
By having a calculation in your comparison, it can invalidate the use of an index. This usually happens when the datatype of the calculation result is different from the datatype of the column being indexed. Sometimes the cost of calculation is large if it has to be repeated enough times (eg from lots of joins). One solution is to store the calculated value in a special column, eg:
CREATE TABLE TestInstances (
...
nextSchoolYearID int);
And use a trigger or logic to maintain nextSchoolYearID = fkSchoolYearID + 1, then use
ON TestInstances.fkSchoolYearID = TestInstancesPre.nextSchoolYearID)
Also, you have AND StudentTests.pkStudentTestID IN (SELECT * FROM #tempTests) in the first join's on clause, but the values in #tempTests are not related to either table.
Try moving that predicate to a where clause at the end, ie:
SELECT
...
WHERE StudentTests.pkStudentTestID IN (SELECT * FROM #tempTests)
Doing this means SELECT * FROM #tempTests will only get executed once, instead of being executed for every row combination of TestInstances and StudentTests.