Bonjour,

J'avais déjà remarqué (mais je viens de m'y reconfronter) que malheureusement Sql Server 2005 n'avait pas un comportement très intelligent vis à vis des conditions de jointure/filtre impliquant des constantes.

Exemple (à lire en diagonale, sa complexité importe nullement) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
declare @lastName varchar(200)
declare @firstName varchar(200)
declare @dateTime datetime
declare @ClubId int
declare @pageIndex int
declare @pageSize int

set @clubid = 1023
set @lastName = null
set @firstName = null
set @dateTime = 0
set @pageIndex = 1
set @pageSize = 5


SELECT
    Id
    , FederalNumber
    , Lname
    , Fname
    , Birthdate
    , HomeClub
    , ShortName
    , DENSE_RANK() OVER (ORDER BY LnameOK, FnameOK, BirthdateOK) AS GROUPID
    , ExpirationDate
FROM (
    SELECT 
        M1.Id
        , M1.FederalNumber
        , M1.Lname
        , M1.Fname
        , M1.Birthdate
        , M1.HomeClub
        , M1.ShortName
        , M1.ExpirationDate

        , LnameOK
        , FnameOK
        , BirthdateOK
        , COUNT(*) OVER (PARTITION BY LnameOK, FnameOK, BirthdateOK) AS CNT_All
		, SUM(CASE WHEN @ClubId IS NULL OR M1.HomeClub = @ClubId THEN 1 ELSE 0 END) OVER (PARTITION BY LnameOK, FnameOK, BirthdateOK) AS CNT_Club
    FROM dbo.VCentral_MemberDetails AS M1
    CROSS APPLY (
        SELECT
            CASE WHEN @lastName IS NULL THEN NULL ELSE M1.LName END AS LnameOK
            , CASE WHEN @firstName IS NULL THEN NULL ELSE M1.Fname END AS FnameOK
            , CASE WHEN @dateTime IS NULL THEN NULL ELSE M1.Birthdate END AS BirthdateOK
    ) AS Part
    WHERE (@lastName IS NULL OR M1.LName LIKE @lastName + '%')
    AND (@firstName IS NULL OR M1.Fname LIKE @firstName + '%')
    AND (@dateTime IS NULL OR @dateTime = 0 OR M1.Birthdate = @dateTime)
) EXT
WHERE CNT_All > 1
AND CNT_Club > 0
On repère deux conditions dont la résolution devrait être immédiate, les deux constante validant ces conditions.
Pourtant Sql Server va quand même faire des traitements pour vérifier la condition en entier ce qui peut s'avérer très lourd (des données supplémentaires à récupérer).

J'ai trouvé (mais je ne prétendrai pas être le seul) un moyen à prioris très efficace pour parer à cela : rendre conditionnel la récupération même de ces données.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
SELECT
    Id
    , FederalNumber
    , Lname
    , Fname
    , Birthdate
    , HomeClub
    , ShortName
    , DENSE_RANK() OVER (ORDER BY LnameOK, FnameOK, BirthdateOK) AS GROUPID
    , ExpirationDate
FROM (
    SELECT 
        M1.Id
        , M1.FederalNumber
        , M1.Lname
        , M1.Fname
        , M1.Birthdate
        , M1.HomeClub
        , M1.ShortName
        , M1.ExpirationDate

        , LnameOK
        , FnameOK
        , BirthdateOK
        , COUNT(*) OVER (PARTITION BY LnameOK, FnameOK, BirthdateOK) AS CNT_All
		, SUM(CASE WHEN @ClubId IS NULL OR M1.HomeClub = @ClubId THEN 1 ELSE 0 END) OVER (PARTITION BY LnameOK, FnameOK, BirthdateOK) AS CNT_Club
    FROM dbo.VCentral_MemberDetails AS M1
    CROSS APPLY (
        SELECT
            CASE WHEN @lastName IS NULL THEN NULL ELSE M1.LName END AS LnameOK
            , CASE WHEN @firstName IS NULL THEN NULL ELSE M1.Fname END AS FnameOK
            , CASE WHEN @dateTime IS NULL THEN NULL ELSE M1.Birthdate END AS BirthdateOK
    ) AS Part
    WHERE (@lastName IS NULL OR (SELECT M1.LName WHERE @lastName IS NOT NULL) LIKE @lastName + '%')
    AND (@firstName IS NULL OR (SELECT M1.Fname WHERE @firstName IS NOT NULL) LIKE @firstName + '%')
    AND (@dateTime IS NULL OR @dateTime = 0 OR (SELECT M1.Birthdate WHERE @firstName IS NOT NULL) = @dateTime)
) EXT
WHERE CNT_All > 1
AND CNT_Club > 0
Et là ça va beaucoups plus vite, surtout si on a quelques indexes qui font mouche.

J'espère que ça pourra en aider certains, car je sais que bcp de dev se retrouve à devoir faire des queries dont les types de condition varient et qui doivent alors choisir entre un seul query avec plusieurs constantes (variables) ou un query dynamique.