简体   繁体   中英

MS Access SQL Join Performance Improvement

I was hoping for some help on how I can improve the query below which is taking an abosolute age to execute.

I'm aware it's the LEFT JOIN that's causing the statement to run so slowly but I have no idea how else I could run the query to improve the performance and return the required results.

Query

SELECT 
    s.id, s.first_name, s.last_name, COUNT(a.AbsenceId)
FROM ((
      dbo_ds_staff AS s
      INNER JOIN dbo_ds_team_staff_member AS tsm ON s.id=tsm.staff_id
    )
    INNER JOIN dbo_ds_team_leader AS tl ON tsm.team_id=tl.team_id
)
LEFT JOIN ct_adt_Absence AS a ON s.id=a.StaffId
  WHERE 
     tl.staff_id=2169
     And tsm.start_date<NOW() 
     And (
        tsm.end_date>=NOW() 
        Or tsm.end_date Is Null
    ) 
    And tl.start_date<NOW()
    And (
     tl.end_date>=NOW() 
     Or tl.end_date Is Null
   )
   GROUP BY s.id, s.first_name, s.last_name
   ORDER BY s.first_name, s.last_name;

If there's any further information I can give to assist, please let me know! Thanks

As suggested in the comments to the question, a pass-through query in Access might speed things up by pushing the processing of the SQL Server tables onto SQL Server itself. For example, a pass-through query named [ptqStaffList] with SQL

SELECT 
    s.id, s.first_name, s.last_name
FROM
    dbo.ds_staff AS s
    INNER JOIN 
    dbo.ds_team_staff_member AS tsm 
        ON s.id=tsm.staff_id
    INNER JOIN 
    dbo.ds_team_leader AS tl 
        ON tsm.team_id=tl.team_id
WHERE tl.staff_id=2169
    AND tsm.start_date < CURRENT_TIMESTAMP 
    AND (tsm.end_date >= CURRENT_TIMESTAMP OR tsm.end_date IS NULL)
    AND tl.start_date < CURRENT_TIMESTAMP
    AND (tl.end_date >= CURRENT_TIMESTAMP OR tl.end_date IS NULL)

...which looks like this in Access...

ptq.png

...returns:

id  first_name  last_name
--  ----------  ---------
1   Gord        Thompson

We can then use that in a regular SELECT query with the local Access table

SELECT 
    s.id, 
    s.first_name, 
    s.last_name, 
    COUNT(a.AbsenceId) AS AbsenceCount
FROM
    ptqStaffList AS s
    LEFT JOIN 
    ct_adt_Absence AS a 
        ON s.id=a.StaffId
   GROUP BY s.id, s.first_name, s.last_name
   ORDER BY s.first_name, s.last_name;

returning

id  first_name  last_name  AbsenceCount
--  ----------  ---------  ------------
1   Gord        Thompson              1
SELECT s.*, COUNT(a.AbsenceId)
FROM
    (SELECT s.id, s.first_name, s.last_name
    FROM ((dbo_ds_staff AS s
    INNER JOIN dbo_ds_team_staff_member AS tsm ON s.id=tsm.staff_id)
    INNER JOIN dbo_ds_team_leader AS tl ON tsm.team_id=tl.team_id)
    WHERE tl.staff_id=2169 And tsm.start_date<NOW() And (tsm.end_date>=NOW() Or tsm.end_date Is Null) And tl.start_date<NOW() And (tl.end_date>=NOW() Or tl.end_date Is Null)
    GROUP BY s.id
    ORDER BY s.first_name, s.last_name) as s
LEFT JOIN ct_adt_Absence AS a ON s.id=a.StaffId
GROUP BY s.id

I would select users first and then add the LEFT JOIN to count absence.

Also I don't see why you need the grouping by first_name and last_name

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM