Оптимизация запроса для построения средних - PullRequest
0 голосов
/ 26 февраля 2009

Недавно я создал запрос в SQL, который я могу использовать для просмотра нашего журнала платежей и определения среднего числа платежей, выполненных за час в течение определенного периода времени. Я уверен, что существуют сторонние приложения для составления отчетов, которые гораздо лучше подходят для выполнения того типа вычислений, который я пытаюсь выполнить, но просто для удовольствия, мне любопытно посмотреть, какие другие методы вы все можете использовать T-SQL), чтобы получить данные, которые я ищу. Я знаю, что это глупый вопрос, поэтому я не буду обижаться, если вы проголосуете против меня. Но для всех, кому скучно, как мне, не стесняйтесь размещать другие ваши решения.

Таблица настроена с помощью столбца [CreateDate], который представляет собой значение DATETIME, когда платеж публикуется в учетной записи. Я использую это, чтобы определить, в какой час они произвели оплату.

CREATE TABLE #TempTimes
(
    [Time] DATETIME,
)

DECLARE @numDays INT
SET @numDays = 10
DECLARE @time DATETIME
SET @time = DATEADD(dd, DATEDIFF(dd, 0, GETDATE() - @numDays), 0)

WHILE @time < GETDATE()
BEGIN
    INSERT #TempTimes
    VALUES (@time)

    SET @time = DATEADD(hour, 1, @time)
END
GO
/*
I have to join in a table with all of the hours for the time span I'm querying against, 
because otherwise, the AVG function won't calculate in the hours where no payments were made. 
*/

SELECT DATEPART(hour, [Time]) [Hour], AVG(CAST([Count] AS DECIMAL)) [Average]
FROM 
(
    SELECT [Time], CASE WHEN [Count] IS NULL THEN 0 ELSE [Count] END [Count]
    FROM #TempTimes tt
    LEFT JOIN 
    (
        SELECT DATEADD(hour, DATEDIFF(hour, 0, [CreateDate]), 0) [hour], COUNT(*) [Count]
        FROM [dbo].[PaymentLog]
        GROUP BY DATEADD(hour, DATEDIFF(hour, 0, [CreateDate]), 0)
    ) t1 ON t1.[hour] = tt.[time]
) t2
GROUP BY DATEPART(hour, tt.[Time])
GO

DROP TABLE #TempTimes
GO

CJ

Ответы [ 2 ]

1 голос
/ 26 февраля 2009

Я думаю, что это довольно изящный метод. Это позволяет избежать использования таблицы Hours (или временной таблицы, как вы используете). Недостатком является то, что он показывает только значения часов, в которые был произведен платеж. Пусть передний конец вставит все 0. :)

CREATE TABLE dbo.Payments
(
    payment_id  INT IDENTITY    NOT NULL,
    create_date DATETIME        NOT NULL,
    CONSTRAINT PK_Payments PRIMARY KEY CLUSTERED (payment_id)
)
GO

INSERT INTO dbo.Payments (create_date)
SELECT '2009-02-25 12:00:00.000' UNION
SELECT '2009-02-25 12:45:00.000' UNION
SELECT '2009-02-25 12:30:00.000' UNION
SELECT '2009-02-25 13:10:00.000' UNION
SELECT '2009-02-25 13:22:00.000' UNION
SELECT '2009-02-25 14:09:00.000' UNION
SELECT '2009-02-25 14:40:00.000'
GO

SELECT
    CAST(CONVERT(VARCHAR(13), T1.create_date, 121) + ':00:00.000' AS DATETIME),
    COUNT(T3.payment_id) + 1
FROM
    dbo.Payments T1
LEFT OUTER JOIN dbo.Payments T2 ON
    T2.create_date >= CAST(CONVERT(VARCHAR(13), T1.create_date, 121) + ':00:00.000' AS DATETIME) AND
    T2.create_date <  T1.create_date
LEFT OUTER JOIN dbo.Payments T3 ON
    T3.create_date >= T1.create_date AND
    T3.create_date <  DATEADD(hh, 1, CAST(CONVERT(VARCHAR(13), T1.create_date, 121) + ':00:00.000' AS DATETIME)) AND
    T3.payment_id <> T1.payment_id
WHERE
    T2.payment_id IS NULL
GROUP BY
    CAST(CONVERT(VARCHAR(13), T1.create_date, 121) + ':00:00.000' AS DATETIME)
GO
1 голос
/ 26 февраля 2009

IIUC вы фильтруете из основной таблицы, используя соединение с временной таблицей.

Почему бы не отбросить объединение и просто использовать предложение where? Если вы хотите, чтобы показывались все часы, выполните объединение после до конца работы или используйте какой-нибудь союз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...