Агрегировать и считать отдельные значения с помощью объединения - PullRequest
0 голосов
/ 17 марта 2020

Этот вопрос представляет собой смесь этих дубликатов:

Мне просто не удается заставить его работать сразу.

У меня есть две таблицы:

TABLE A
IntervalId    Starts  Ends
-------------------------
1              0      10
2             10      25
3             25      32
4             32      40

TABLE B
Id            ErrorType    Starts    Ends
----------------------------------------
1                   666       0      25
2                   666       10     32
3                   777       0      32
4                   666       25     40
5                   777       10     25

Начиная с временных интервалов в таблице B, я пытаюсь считать и перечислять , в каждом интервале типы ошибок, которые могли произойти в течение этого интервала. И удалить дубликаты .

Обратите внимание, что в таблице B нет ни начала, ни конца, которых бы не было в таблице A (из них была сгенерирована таблица A).

результат с дубликатами будет такой:

Starts      Ends        ErrorsCount      Errors
-----------------------------------------------
0           10          2                 666, 777
10          25          4                 666, 666, 777, 777
25          32          3                 666, 777, 666
32          40          1                 666

Результат, который я ищу, равен без дубликатов :

Starts      Ends        DistinctErrorsCnt  DistinctErrors
-----------------------------------------------
0           10          2                 666, 777
10          25          2                 666, 777
25          32          2                 666, 777
32          40          1                 666

Вот мой атаман, но я не могу понять, как получить ErrorType из разряда, который делает «отличный» сервер без SQL, жалуясь, что он не в агрегате или группе. Или, как только я поместил его в группу, все различные типы ошибок будут стерты первыми. В итоге я получаю только 666.

SELECT 
    IntervalId,
    Starts,
    Ends,
    COUNT([TableB].ErrorType) as DistinctErrorsCnt,
    DistinctErrors= STRING_AGG([TableB].ErrorType, ',')
FROM
(
    SELECT DISTINCT  
        [TableA].IntervalId,

    FROM TableB LEFT JOIN TableA ON
        (
            [TableA].Starts= [TableB].Starts
        OR [TableA].Ends = [TableB].Ends
        OR ([TableA].Starts >= [TableB].Starts AND [TableA].Ends <= [TableB].Ends)

        )
    GROUP BY 
        [TableA].IntervalId,
        [TableA].Starts, 
        [TableA].Ends, 
) NoDuplicates
GROUP BY 
    NoDuplicates.IntervalId,
    NoDuplicates.Starts, 
    NoDuplicates.Starts

Опять же: это не является синтаксически правильным, по причине, которую я объяснил выше.

1 Ответ

0 голосов
/ 17 марта 2020

Вы можете использовать агрегацию:

select 
    a.starts,
    a.ends,
    count(distinct b.errorType) DistinctErrorsCnt,
    string_agg(b.errorType, ', ') within group(order by b.starts) DistinctErrors
from tablea a
inner join tableb b on b.starts >= a.ends and b.ends <= a.start
group by a.intervalId, a.start, a.end

Если вы хотите избежать дубликатов, вы можете использовать подзапрос или, что еще лучше, cross apply:

select
    a.starts,
    a.ends,
    count(*) DistinctErrorsCnt,
    string_agg(b.errorType, ', ') within group(order by b.starts) DistinctErrors
from tablea a
cross apply (
    select distinct errorType from tableb b where b.starts >= a.ends and b.ends <= a.start
) b
group by a.intervalId, a.start, a.end
...