Самый эффективный способ получить количество идентификаторов Где INT в (Case?) Группах - PullRequest
0 голосов
/ 03 мая 2019

Получите следующий запрос:

    SELECT 
        DISTINCT(ID)
        , CAST(FirstDate AS DATE) AS FirstDate
        , CAST(LastDate AS DATE) As LastDate
        , DATEDIFF(HOUR, FirstDate, LastDate) AS [Diff]
    FROM
        Table
    GROUP BY 
        ID
        , FirstDate
        , LastDate

Отсюда я хочу разделить [Diff] на группы, а затем получить счет, то есть считать где [Diff] между 0-9, 10-19,20-29 ...

Приведенный выше запрос извлекает что-то вроде:

ID |  FirstDate  |  LastDate  | Diff
------------------------------------
1  | 2019-03-31  | 2019-04-01 | 26
2  | 2019-03-31  | 2019-04-01 | 32
3  | 2019-04-01  | 2019-04-01 | 9
4  | 2019-03-31  | 2019-04-01 | 15
5  | 2019-04-01  | 2019-04-01 | 5

Ищите это, то есть количество идентификаторов на группу Diff

0-10 | 11-19 | 20-29
---------------------
  2  |   1   |  2

Ответы [ 5 ]

0 голосов
/ 07 мая 2019

Вы можете просто использовать Общие табличные выражения (CTE), а затем запросить CTE, чтобы получить желаемый результат.Вы можете создать CTE, как показано ниже:

WITH CTE AS
(
    SELECT 
        Id,
        [Range] = 
        CASE
            WHEN DATEDIFF(HOUR, FirstDate, LastDate) between 0 and 10 THEN '0-10'
            WHEN DATEDIFF(HOUR, FirstDate, LastDate) between 11 and 19 THEN '11-19'
            WHEN DATEDIFF(HOUR, FirstDate, LastDate) between 20 and 32 THEN '20-32'
        END
    FROM
        Table
)

Вы можете написать запрос GROUP BY сразу после CTE, чтобы получить количество диапазонов Diff.

SELECT COUNT(Id) Count, Range FROM CTE GROUP BY Range

Выше будетсоздайте вывод, как показано ниже:

Count   Range
2       0-10
1       11-19
2       20-32

Если вам нужен поворотный вывод, как вы упоминали в вопросе, используйте функцию PIVOT сразу после CTE

SELECT 'Count' AS Diff,  
    [0-10],  
    [11-19],  
    [20-32]
FROM  
    (SELECT [Range], Id FROM CTE) AS SourceTable
PIVOT  
(  
    COUNT(Id)
FOR   
    [Range] IN ([0-10],[11-19],[20-32])  
) AS PivotTable;

Вы получите следующий вывод

Diff    0-10    11-19   20-32
Count   2       1       2

Надеюсь, это поможет

0 голосов
/ 03 мая 2019

Вы можете установить размер группы в качестве переменной и рассчитать смещения и счет

DECLARE @GroupSize INT = 10

SELECT
    GroupCount  = SUM(CountInGroup),
    StartIndex  =( Diff / @GroupSize ) * @GroupSize,
    EndIndex    =(( Diff / @GroupSize ) * @GroupSize ) + @GroupSize
FROM
(
    SELECT
        CountInGroup = COUNT(*)
        ,Diff = DATEDIFF(HOUR, FirstDate, LastDate)
    FROM
        YourTable
    GROUP BY
        DATEDIFF(HOUR, FirstDate, LastDate),
        FirstDate,
        LastDate
) AS X
GROUP BY
    Diff / @GroupSize
0 голосов
/ 03 мая 2019

Если вы не знаете, сколько у вас групп, и оператор CASE не подходит, вы можете попробовать что-то вроде этого:

SELECT 
    CONVERT(VARCHAR(5),FLOOR(((diff+.001)*1.0)/10) *10) + 
        '-' + CONVERT(VARCHAR(5),(CEILING(((diff+.001)*1.0)/10) *10)-1),
    count(*)
FROM 
    [Table]
GROUP BY
    CONVERT(VARCHAR(5),FLOOR(((diff+.001)*1.0)/10) *10) + 
        '-' + CONVERT(VARCHAR(5),(CEILING(((diff+.001)*1.0)/10) *10)-1)

РЕДАКТИРОВАТЬ: Сделал это до того, как увидел ваши изменения и желаемый результат. Отсюда вы можете поместить его во временную таблицу и затем развернуть. Я могу помочь вам с этим, если вам нужно.

Ниже приведен код для перевода в нужный вам формат. Вы должны связываться с StartIndex и EndIndex, чтобы правильно распределить свои группы.

CREATE table #temp(DiffGroup varchar(15),StartIndex int, EndIndex int,Num int)

insert into #temp 
SELECT 
    CONVERT(VARCHAR(5),(diff/10) *10) +'-' +CONVERT(VARCHAR(5),(CEILING(diff/10) *10)+9) DiffGroup,
    (diff/10) *10 AS StartIndex, 
    (CEILING(diff/10) *10)+9 AS EndIndex,
    count(*) AS Num
FROM 
    Table
GROUP BY
    CONVERT(VARCHAR(5),(diff/10) *10) +'-' +CONVERT(VARCHAR(5),(CEILING(diff/10) *10)+9),
    (diff/10) *10,
    (CEILING(diff/10) *10)+9

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(DiffGroup) 
            FROM #temp c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT  ' + @cols + ' from 
            (
                select DiffGroup
                    , Num
                from #temp
           ) x
            pivot 
            (
                    SUM(Num)
                for DiffGroup in (' + @cols + ')
            ) p '


execute(@query)

0 голосов
/ 03 мая 2019

Вы можете использовать apply и сделать условное агрегирование:

select sum(case when diff >= 0 and diff < 10 then 1 else 0 end) as [0-9],
       sum(case when diff >= 10 and diff < 20 then 1 else 0 end) as [10-19],
       sum(case when diff >= 20 and diff < 30 then 1 else 0 end) as [20-29]
from table t cross apply
     ( values (DATEDIFF(HOUR, FirstDate, LastDate)) 
     ) tt(diff);
0 голосов
/ 03 мая 2019

Сделайте ваш запрос подзапросом, обернув вокруг него другой запрос. Этот внешний запрос будет использовать положения дел для группировки данных. В операторах case выберите 1, когда находится в диапазоне значений группы, и 0, если нет. СУММА СЛУЧАЙ CASE, чтобы получить счет.

Как это

SELECT
    SUM( CASE WHEN Diff BETWEEN 0 AND 9 THEN 1 ELSE 0 END ) [0_9]
,   SUM( CASE WHEN Diff BETWEEN 10 AND 19 THEN 1 ELSE 0 END ) [10-19]
,   ETC....
  FROM (
    SELECT 
        DISTINCT(ID)
        , FirstDate
        , LastDate
        , DATEDIFF(HOUR, FirstDate, LastDate) AS [Diff]
    FROM
        Table
    GROUP BY 
        ID
        , FirstDate
        , LastDate
) t
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...