Double count result when using INNER JOIN on TSQL

2019-08-29 07:49发布

问题:

I'm using the following query to count all scripts runs, but when there are 2 types for a software, it doubles the count result.

Here is query I'm using:

SELECT 
    p.produto, p.pacote, 
    COUNT(p.produto) AS Execuções, 
    CONVERT(VARCHAR, AVG(DATEDIFF(SECOND, p.inicio, p.fim)) / 60) + ':' + RIGHT('0' + CONVERT(VARCHAR, AVG(DATEDIFF(SECOND, p.inicio, p.fim)) % 60), 2) AS [Tempo Médio (Automatizado)], 
    t.tempo_minutos AS [Tempo Médio (Manual)], 
    CONVERT(VARCHAR, (t.tempo_minutos * 60 - AVG(DATEDIFF(SECOND, p.inicio, p.fim))) / 60) + ':' + RIGHT('0' + CONVERT(VARCHAR, (t.tempo_minutos * 60 - AVG(DATEDIFF(SECOND, p.inicio, p.fim))) % 60), 2) AS [Economia Média], 
    CONVERT(VARCHAR, (t.tempo_minutos * 60 - AVG(DATEDIFF(SECOND, p.inicio, p.fim))) * COUNT(p.produto) / 60)  + ':' + RIGHT('0' + CONVERT(VARCHAR, (t.tempo_minutos * 60 - AVG(DATEDIFF(SECOND, p.inicio, p.fim))) * COUNT(p.produto) % 60), 2) AS [Economia Total]
FROM 
    [log].pdq AS p 
INNER JOIN 
    infra.tempo_medio_execucao AS t ON t.produto = p.produto
WHERE 
    (p.equipamento NOT LIKE 'XXX%') AND (p.status = 'Sucesso')
GROUP BY 
    p.produto, p.pacote, t.tempo_minutos

This query is returning the following result (removed the unnecessary info from the table):

produto  | pacote        | Execuções
---------+---------------+-----------    
SafeSign | Desinstalação | 6
SafeSign | Instalação    | 18
ScanBack | Instalação    | 128

Where it should return:

produto  | pacote        |  Execuções
---------+---------------+-----------    
SafeSign | Desinstalação | 3
SafeSign | Instalação    | 9
ScanBack | Instalação    | 128

In the infra.tempo_medio_execucao table, I have this data:

produto      | pacote        | tempo_minutos 
-------------+---------------+--------------
ScanBack     | Instalação    | 20
Siric Zero   | Instalação    | 20
GRRF         | Instalação    | 90
SICCH        | Instalação    | 15
Outlook 2013 | Instalação    | 25
7-Zip        | Instalação    | 20
7-Zip        | Desinstalação | 20
SafeSign     | Instalação    | 20
SafeSign     | Desinstalação | 20

The table log.pdq will return:

id | produto   | pacote      | inicio                  | fim                     | duracao          | status 
---+-----------+-------------+-------------------------+-------------------------+------------------+--------
1  | ScanBack  | Instalação  | 2018-09-18 11:22:54.000 | 2018-09-18 11:27:43.000 | 00:04:49.0000000 | Sucesso 
2  | ScanBack  | Instalação  | 2018-09-18 12:10:46.000 | 2018-09-18 12:11:04.000 | 00:00:17.0000000 | Sucesso 
3  | ScanBack  | Instalação  | 2018-09-18 12:10:49.000 | 2018-09-18 12:11:17.000 | 00:00:27.0000000 | Sucesso 
4  | GRRF      | Instalação  | 2018-09-18 12:28:43.000 | 2018-09-18 12:29:14.000 | 00:00:30.0000000 | Sucesso

And the view I've created returns: (but for Safesign, it should return 3 and 9, not 6 and 18)

Produto    |  Pacote       | Execuções  | Tempo Médio (Automatizado) | Tempo Médio (Manual) | Economia Média  | Economia Total
-----------+---------------+------------+----------------------------+----------------------+-----------------+----------------
GRRF       | Instalação    | 1          | 0:31                       | 90                   | 89:29           | 89:29
SafeSign   | Desinstalação | 6          | 0:00                       | 20                   | 20:00           | 120:00
SafeSign   | Instalação    | 18         | 1:19                       | 20                   | 18:41           | 336:18
ScanBack   | Instalação    | 128        | 1:23                       | 20                   | 18:37           | 2382:56
SICCH      | Instalação    | 7          | 0:34                       | 15                   | 14:26           | 101:02
Siric Zero | Instalação    | 208        | 0:33                       | 20                   | 19:27           | 4045:36

Thanks in advance!

回答1:

There is really something missing in your question. This seems to produce the correct result; so, I think you need to provide a better example.

DECLARE @pdq TABLE (
    ID int,produto nvarchar(50),pacote nvarchar(50),inicio datetime2,fim datetime2,duracao time, status nvarchar(50),equipamento nvarchar(50)
)

DECLARE @tempo_medio_execucao  TABLE (
    produto nvarchar(50),pacote nvarchar(50),tempo_minutos INT
)

INSERT INTO @pdq(id,produto,pacote,inicio,fim,duracao,status,equipamento) SELECT 1,'ScanBack','Instalação','2018-09-18 11:22:54.000','2018-09-18 11:27:43.000','00:04:49.0000000','Sucesso','Unknown'
INSERT INTO @pdq(id,produto,pacote,inicio,fim,duracao,status,equipamento) SELECT 2,'ScanBack','Instalação','2018-09-18 12:10:46.000','2018-09-18 12:11:04.000','00:00:17.0000000','Sucesso','Unknown'
INSERT INTO @pdq(id,produto,pacote,inicio,fim,duracao,status,equipamento) SELECT 3,'ScanBack','Instalação','2018-09-18 12:10:49.000','2018-09-18 12:11:17.000','00:00:27.0000000','Sucesso','Unknown'
INSERT INTO @pdq(id,produto,pacote,inicio,fim,duracao,status,equipamento) SELECT 4,'GRRF','Instalação','2018-09-18 12:28:43.000','2018-09-18 12:29:14.000','00:00:30.0000000','Sucesso','Unknown'

INSERT INTO @tempo_medio_execucao(produto,pacote,tempo_minutos) SELECT 'ScanBack','Instalação',20
INSERT INTO @tempo_medio_execucao(produto,pacote,tempo_minutos) SELECT 'Siric Zero','Instalação',20
INSERT INTO @tempo_medio_execucao(produto,pacote,tempo_minutos) SELECT 'GRRF','Instalação',90
INSERT INTO @tempo_medio_execucao(produto,pacote,tempo_minutos) SELECT 'SICCH','Instalação',15
INSERT INTO @tempo_medio_execucao(produto,pacote,tempo_minutos) SELECT 'Outlook 2013','Instalação',25
INSERT INTO @tempo_medio_execucao(produto,pacote,tempo_minutos) SELECT '7-Zip','Instalação',20
INSERT INTO @tempo_medio_execucao(produto,pacote,tempo_minutos) SELECT '7-Zip','Desinstalação',20
INSERT INTO @tempo_medio_execucao(produto,pacote,tempo_minutos) SELECT 'SafeSign','Instalação',20
INSERT INTO @tempo_medio_execucao(produto,pacote,tempo_minutos) SELECT 'SafeSign','Desinstalação',20

SELECT 
    p.produto, p.pacote, 
    COUNT(p.produto) AS Execuções, 
    CONVERT(VARCHAR, AVG(DATEDIFF(SECOND, p.inicio, p.fim)) / 60) + ':' + RIGHT('0' + CONVERT(VARCHAR, AVG(DATEDIFF(SECOND, p.inicio, p.fim)) % 60), 2) AS [Tempo Médio (Automatizado)], 
    t.tempo_minutos AS [Tempo Médio (Manual)], 
    CONVERT(VARCHAR, (t.tempo_minutos * 60 - AVG(DATEDIFF(SECOND, p.inicio, p.fim))) / 60) + ':' + RIGHT('0' + CONVERT(VARCHAR, (t.tempo_minutos * 60 - AVG(DATEDIFF(SECOND, p.inicio, p.fim))) % 60), 2) AS [Economia Média], 
    CONVERT(VARCHAR, (t.tempo_minutos * 60 - AVG(DATEDIFF(SECOND, p.inicio, p.fim))) * COUNT(p.produto) / 60)  + ':' + RIGHT('0' + CONVERT(VARCHAR, (t.tempo_minutos * 60 - AVG(DATEDIFF(SECOND, p.inicio, p.fim))) * COUNT(p.produto) % 60), 2) AS [Economia Total]
FROM @pdq AS p 
INNER JOIN @tempo_medio_execucao AS t ON t.produto = p.produto
WHERE (p.equipamento NOT LIKE 'XXX%') AND (p.status = 'Sucesso')
GROUP BY 
    p.produto, p.pacote, t.tempo_minutos


回答2:

I suspect that this does what you specify in the question:

SELECT p.produto, p.pacote, 
       COUNT(DISTINCT p.produto) AS Execuções, 
       . . .

You would be getting duplicates from your joins -- basically unexpected matches.

However, it is quite possible (likely) that other columns are also inaccurate. If this fixes the issue with Execuções, but you still have other issues, then ask another question. Be very clear about sample data, desired results, and what needs to be fixed.