Comment forcer SQL Server à exécuter une requête dans un ordre particulier
-
22-07-2019 - |
Question
J'ai la requête suivante
DECLARE @userId INT DECLARE @siteId INT SET @siteId = -1 SET @userId = 1828 SELECT a.id AS alertId, a.location_id, a.alert_type_id, a.event_id, a.user_id, a.site_id, a.accepted_by FROM alerts AS a JOIN alert_types AS ats ON a.alert_type_id = ats.id JOIN events AS tr ON a.event_id = tr.event_id WHERE tr.end_Time IS null AND tr.status_id = 0 AND ats.code = 'E' AND a.site_id in (SELECT * FROM dbo.udf_get_event_sitelist(@siteId, @userId))
L'exécution de cette requête prend entre 5 et 17 secondes. Toutefois, dans de nombreuses circonstances, la fonction dbo.udf_get_event_sitelist (@siteId, @userId) ne renvoie aucune ligne. Par conséquent, la requête ne trouve aucune donnée.
Comment puis-je forcer SQL Server à exécuter d'abord la fonction définie par l'utilisateur? J'apprécie le fait que je puisse réécrire la requête dans une procédure stockée et effectuer la sous-sélection en premier, mais j'aimerais toutefois le faire si possible dans une seule instruction SQL.
La solution
créer le " FROM " table le jeu de résultats de la fonction et y associe les autres tables
DECLARE @userId INT
DECLARE @siteId INT
SET @siteId = -1
SET @userId = 1828
SELECT a.id AS alertId,
a.location_id,
a.alert_type_id,
a.event_id,
a.user_id,
a.site_id,
a.accepted_by
FROM (SELECT * FROM dbo.udf_get_event_sitelist(@siteId, @userId)) dt
JOIN alerts AS a ON dt.site_id=a.site_id
JOIN alert_types AS ats ON a.alert_type_id = ats.id
JOIN events AS tr ON a.event_id = tr.event_id
WHERE tr.end_Time IS null
AND tr.status_id = 0
AND ats.code = 'E'
Autres conseils
vous pouvez sélectionner les résultats de udf_get_event_sitelist dans une variable de table et ne poursuivre que la grande requête si @@ rowcount > 0
Le problème que vous rencontrez lors de l’utilisation de fonctions inline est qu’elles peuvent être réévaluées pour chaque ligne renvoyée dans SELECT. Cela signifie que si l'instruction SELECT renvoie 100 lignes, la fonction peut être exécutée 100 fois.
Vous devriez vraiment suivre le conseil de Sambo99 et l'extraire dans une variable de table (ou dans une table temporaire si vous pensez qu'elle a besoin d'index).
Modifiez également votre fichier UDF pour ne renvoyer que le site_ID car je suppose que vous ne devez pas supprimer toutes les colonnes (*)
SELECT * FROM dbo.udf_get_event_sitelist(@siteId, @userId)
à
SELECT site_id FROM dbo.udf_get_event_sitelist(@siteId, @userId)