Bonjour,

Je me pose une question plus ou moins générale quant au développement dans l'environnement AZURE de Microsoft.

Le coût des Sql Database sur Azure dépend des DTUs. Or, je ne sais pas trop comment est calculé un DTU (et d'après ce qu'on m'a dit on ne trouve pas la formule sur le net car Microsoft ajuste encore régulièrement le tir).

Du coup, vaut-il mieux faire une requête ensembliste complexe en db ou bien vaut-il mieux rapatrier le jeu de données en mémoire du service qui attaque la db et faire le traitement de manière itérative dans le service (service qui est aussi sur Azure et on paie au CPU utilisé là je crois )?

Quand je parle requête complexe, je parle de requête dans ce genre-ci (explications en-dessous):
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
DECLARE @CMP_ID UNIQUEIDENTIFIER = '1E5BF419-6AFD-4448-AC79-A12F9B24CCF2' ;DECLARE @TOOL_ID UNIQUEIDENTIFIER = 'EDB28E73-C26D-42BF-2775-08D757DAA44F';
DECLARE @DATE_FROM DATE = '20191201';
DECLARE @DATE_TO DATE = '20200131';
 
 
WITH
SITE_IN AS ( --Dates d'entrée entre les bornes
    SELECT    DISTINCT 
            TS.ToolId, 
            TS.SiteId, 
            TS.ValidationDate AS 'DATE_IN'
    FROM    Tools_Sites TS
                INNER JOIN TOOLS T
                    ON    TS.ToolId = T.Id
                    AND T.CompanyId = @CMP_ID
    WHERE    TS.IsLeaving = 0
        AND 1 = CASE
                    WHEN @TOOL_ID IS NULL THEN 1
                    WHEN TS.ToolId = @TOOL_ID THEN 1
                    ELSE 0
                END
        AND TS.ValidationDate BETWEEN @DATE_FROM AND DATEADD(DAY, 1, @DATE_TO)
    UNION ALL --Plus une date d'entrée à la date de la borne inférieure dans le cas où la sortie est entre les bornes mais pas l'entrée
    SELECT    TSA.TOOLID,
            TSA.SITEID,
            @DATE_FROM
    FROM    Tools_Sites TSA
                INNER JOIN TOOLS T
                    ON    TSA.ToolId = T.Id
                    AND T.CompanyId = @CMP_ID
    WHERE    TSA.IsLeaving = 1
        AND NOT EXISTS(    SELECT    1 
                        FROM    Tools_Sites TSB
                                    INNER JOIN TOOLS T
                                        ON    TSB.TOOLID = T.Id
                                        AND T.CompanyId = @CMP_ID
                        WHERE    TSB.IsLeaving = 0
                            AND TSB.ValidationDate <= TSA.ValidationDate
                            AND TSB.ToolId = TSA.ToolId
                            AND TSB.SiteId = TSA.SiteId
                            AND TSB.ValidationDate BETWEEN @DATE_FROM AND DATEADD(DAY, 1, @DATE_TO))
    AND 1 = CASE
                WHEN @TOOL_ID IS NULL THEN 1
                WHEN TSA.ToolId = @TOOL_ID THEN 1
                ELSE 0
            END
    AND TSA.ValidationDate BETWEEN @DATE_FROM AND DATEADD(DAY, 1, @DATE_TO)
),
SITE_OUT AS (--Dates de sorties entres les bornes
    SELECT    DISTINCT
            TS.TOOLID,
            TS.SITEID,
            TS.VALIDATIONDATE AS 'DATE_OUT'
    FROM    Tools_Sites TS
                INNER JOIN TOOLS T
                    ON    TS.ToolId = T.ID
                    AND T.CompanyId = @CMP_ID
    WHERE    IsLeaving = 1
    AND 1 = CASE
                WHEN @TOOL_ID IS NULL THEN 1
                WHEN TS.ToolID = @TOOL_ID THEN 1
                ELSE 0
            END
    AND TS.ValidationDate BETWEEN @DATE_FROM AND DATEADD(DAY, 1, @DATE_TO)
),
SITE_IN_OUT AS (
    SELECT    SI.TOOLID,
            SI.SITEID,
            SI.DATE_IN,
            (    
                SELECT    COALESCE(MIN(DATE_OUT), CAST(@DATE_TO AS DATE)) --Si pas de date de sortie, on prend la date de la borne supérieure
                FROM    SITE_OUT SO
                WHERE    SO.TOOLID = SI.TOOLID
                    AND SO.SITEID = SI.SITEID
                    AND SO.DATE_OUT >= SI.DATE_IN
            ) AS 'DATE_OUT'
    FROM    SITE_IN SI
),
SITE_DAYS_ALL AS (
    SELECT    TOOLID,
            SITEID,
            CAST(DATE_IN AS DATE) AS 'DATE_IN',
            CAST(DATE_OUT AS DATE) AS 'DATE_OUT',
            --DATEDIFF(DAY, CAST(DATE_IN AS DATE), CAST(DATE_OUT AS DATE)) + 1 AS 'DAYS_ON_SITE',
            ROW_NUMBER() OVER (ORDER BY TOOLID, SITEID, DATE_IN) AS 'RN'
    FROM    SITE_IN_OUT
),
SITE_DAYS_GROUPING AS (
    SELECT    TOOLID,
            SITEID,
            DATE_IN,
            DATE_OUT,
            1 AS 'GROUPING_COLUMN',
            RN
    FROM    SITE_DAYS_ALL A
    WHERE    RN = 1
    UNION ALL
    SELECT    B.ToolId,
            B.SITEID,
            B.DATE_IN,
            B.DATE_OUT,
            CASE
                WHEN B.DATE_IN = SDG.DATE_OUT THEN SDG.GROUPING_COLUMN
                ELSE SDG.GROUPING_COLUMN + 1
            END AS 'GROUPING_COLUMN',
            B.RN
    FROM    SITE_DAYS_ALL B
                INNER JOIN SITE_DAYS_GROUPING SDG
                    ON    B.RN = SDG.RN + 1
),
SITE_DAYS_GROUPED AS (
    SELECT    ToolId,
            SITEID,
            MIN(DATE_IN) AS 'DATE_IN',
            MAX(DATE_OUT) AS 'DATE_OUT',
            DATEDIFF(DAY, MIN(DATE_IN), MAX(DATE_OUT)) + 1 AS 'DAYS_ON_SITE'
    FROM    SITE_DAYS_GROUPING
    GROUP BY
            TOOLID,
            SITEID,
            GROUPING_COLUMN
)
SELECT    * 
FROM    SITE_DAYS_GROUPED
ORDER BY 
        SiteId, 
        DATE_IN
Sur le principe la requête n'est pas dure à comprendre. Il s'agit d'une requête sur une table de jointure entre une table d'outils et une table de sites dont voici la structure se trouve plus bas de manière à avoir le nombre de jour qu'un outil a passé sur un site.
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
CREATE TABLE [dbo].[Tools_Sites](    [Id] [uniqueidentifier] NOT NULL,
    [ToolId] [uniqueidentifier] NOT NULL,
    [SiteId] [uniqueidentifier] NOT NULL,
    [SiteLocationType] [int] NOT NULL,
    [IsCurrentAssignedSite] [bit] NOT NULL,
    [IsLeaving] [bit] NOT NULL,
    [ValidationDate] [datetimeoffset](7) NOT NULL,
    [Created] [datetimeoffset](7) NOT NULL,
    [CreatedByUserId] [uniqueidentifier] NOT NULL,
    [CreatedByUserName] [nvarchar](256) NOT NULL,
    [Modified] [datetimeoffset](7) NOT NULL,
    [ModifiedByUserId] [uniqueidentifier] NOT NULL,
    [ModifiedByUserName] [nvarchar](256) NOT NULL,
 CONSTRAINT [PK_Tools_Sites] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
 
 
ALTER TABLE [dbo].[Tools_Sites] ADD  CONSTRAINT [DF_Tools_Sites_Id]  DEFAULT (newsequentialid()) FOR [Id]
GO
 
 
ALTER TABLE [dbo].[Tools_Sites]  WITH NOCHECK ADD  CONSTRAINT [FK_Tools_Sites_SiteLocationTypes] FOREIGN KEY([SiteLocationType])
REFERENCES [dbo].[SiteLocationTypes] ([Id])
GO
 
 
ALTER TABLE [dbo].[Tools_Sites] CHECK CONSTRAINT [FK_Tools_Sites_SiteLocationTypes]
GO
 
 
ALTER TABLE [dbo].[Tools_Sites]  WITH NOCHECK ADD  CONSTRAINT [FK_Tools_Sites_Sites] FOREIGN KEY([SiteId])
REFERENCES [dbo].[Sites] ([Id])
GO
 
 
ALTER TABLE [dbo].[Tools_Sites] CHECK CONSTRAINT [FK_Tools_Sites_Sites]
GO
 
 
ALTER TABLE [dbo].[Tools_Sites]  WITH NOCHECK ADD  CONSTRAINT [FK_Tools_Sites_Tools] FOREIGN KEY([ToolId])
REFERENCES [dbo].[Tools] ([Id])
GO
 
 
ALTER TABLE [dbo].[Tools_Sites] CHECK CONSTRAINT [FK_Tools_Sites_Tools]
GO
Qu'en pensez-vous ?
Question annexe : Y a-t-il moyen de simplifier cette requête ? Il est possible que je sois passé à côté de quelque chose et qu'il y avait moyen de faire plus simple.

EDIT : Concernant la structure de la table de jointure, il s'agit d'un projet que je reprends et je n'ai pas la possibilité de la modifier pour le moment. La colonne de ValidationDate indique la date à partir de laquelle la ligne est active et la colonne IsLeaving indique si la ligne est une entrée ou une sortie du site. J'aurais préféré avec les colonnes DateIn et DateOut mais bon... J'dois faire avec ça.