Как правильно GROUP BY столбцы даты и времени в определенных интервалах? - PullRequest
0 голосов
/ 10 января 2012

Я делаю хранимую процедуру в MSSQL и хочу сгруппировать результаты по интервальному дню, хотя я не уверен, что это правильно:

(это часть)

    INSERT @Results
    (
        [Day],
        [Month],
        [Year],
        [Result]
    )
    SELECT
        DATEPART(DD, DATEADD(MI, @GmtOffset, EventDate)),
        DATEPART(MM, DATEADD(MI, @GmtOffset, EventDate)),
        DATEPART(YY, DATEADD(MI, @GmtOffset, EventDate)),
        Result = CASE WHEN @Metric = 'Take Rate' THEN NULL ELSE COUNT(*) END
    FROM BundleEvent
    WHERE BundleEventTypeId = CASE WHEN @Metric = 'Take Rate' THEN @TypeTakeId ELSE @BundleEventTypeId END
        AND EventDate >= @StartTime AND EventDate <= @EndTime
    GROUP BY
        DATEPART(YY, DATEADD(MI, @GmtOffset, EventDate)),
        DATEPART(MM, DATEADD(MI, @GmtOffset, EventDate)),
        DATEPART(DD, DATEADD(MI, @GmtOffset, EventDate))

Боюсь, что в конечном итоге данные будут сгруппированы по дате, когда год или месяц не имеют значения. Кто-нибудь знает, правильно ли я это делаю? EventDate - это поле DateTime, в которое я хочу добавить GROUP BY по интервалу дня.

Спасибо

EDIT: Это правильный путь, простой обмен форматами ... иногда мне нужно больше кофе.

INSERT @Results
(
    [Date],
    [Result]
)
SELECT
    CAST(DATEADD(MI, @GmtOffset, BundleEvent.EventDate) AS DATE),
    Result = CASE WHEN @Metric = 'Take Rate' THEN 0 ELSE COUNT(*) END
FROM dbo.BundleEvent WITH (NOLOCK)
JOIN dbo.BundleUser WITH (NOLOCK)
    ON BundleEvent.BundleId = BundleUser.BundleId
JOIN dbo.Bundle WITH (NOLOCK)
    ON BundleEvent.BundleId = Bundle.BundleId
WHERE BundleEvent.EventDate >= @StartTimeGmt AND BundleEvent.EventDate <= @EndTimeGmt
    AND BundleEvent.BundleEventTypeId = CASE WHEN @Metric = 'Take Rate' THEN @TypeTakeId ELSE @BundleEventTypeId END
    AND BundleUser.UserId = CASE WHEN @UserId IS NULL THEN BundleUser.UserId ELSE @UserId END
    AND Bundle.BundleType = 1
GROUP BY
    CAST(DATEADD(MI, @GmtOffset, BundleEvent.EventDate) AS DATE)

Затем я делаю суб-сравнение с форматом обмена:

            CAST(
                (SELECT COUNT(*)
                FROM dbo.BundleEvent WITH (NOLOCK)
                JOIN dbo.BundleUser WITH (NOLOCK)
                    ON BundleEvent.BundleId = BundleUser.BundleId
                JOIN dbo.Bundle WITH (NOLOCK)
                    ON BundleEvent.BundleId = Bundle.BundleId
                WHERE CAST(DATEADD(MI, @GmtOffset, BundleEvent.EventDate) AS DATE) = [Date]
                AND BundleEvent.BundleEventTypeId = @TypeTakeId
                AND BundleUser.UserId = CASE WHEN @UserId IS NULL THEN BundleUser.UserId ELSE @UserId END
                AND Bundle.BundleType = 1)
                AS DECIMAL(5,2)

Таким образом, по сути, запрос соответствует правильно и использует новый формат.

1 Ответ

0 голосов
/ 10 января 2012

Так как вы не используете и агрегируете (кроме Count (*), вы уверены, что хотите использовать GROUP BY? Использование DISTINCT создаст одну запись вставки для всех совпадающих дат; возможно, что-то вроде:

DECLARE @DATE_GMT datetime
SET @DATE_GMT=DATEADD(MI, @GmtOffset, EventDate)
INSERT @Results
(
    [Day],
    [Month],
    [Year],
    [Result]
)
SELECT DISTINCT
    DATEPART(DD, @DATE_GMT),
    DATEPART(MM, @DATE_GMT),
    DATEPART(YY, @DATE_GMT),
    Result = CASE WHEN @Metric = 'Take Rate' THEN NULL ELSE COUNT(*) END
FROM BundleEvent
WHERE BundleEventTypeId = CASE WHEN @Metric = 'Take Rate' THEN @TypeTakeId ELSE @BundleEventTypeId END
    AND EventDate Between @StartTime AND @EndTime
...