SQL Grouping around gaps

Строгое-Brocot Дерево вызывает довольно естественный способ приблизить вещественные числа частями с простыми знаменателями.

7
задан KM. 19 October 2009 в 18:04
поделиться

3 ответа

Почему все так категорически против использования стола для такого рода вещей? Таблица чисел или календарная таблица занимает так мало места и, вероятно, находится в памяти, если на нее в любом случае ссылаются. Вы также можете легко получить таблицу чисел на лету, используя ROW_NUMBER (). Использование таблицы чисел может помочь в понимании запроса. Но вот не такой простой пример, трюк, который я недавно перенял у Пламена Ратчева, надеюсь, он поможет.

DECLARE @wtns TABLE
(
    WTN    CHAR(12),
    [Date] SMALLDATETIME
);

INSERT @wtns(WTN, [Date])
          SELECT '555-111-1212','2009-01-01'
UNION ALL SELECT '555-111-1212','2009-01-02'
UNION ALL SELECT '555-111-1212','2009-01-03'
UNION ALL SELECT '555-111-1212','2009-01-15'
UNION ALL SELECT '555-111-1212','2009-01-16'
UNION ALL SELECT '212-999-5555','2009-01-01'
UNION ALL SELECT '212-999-5555','2009-01-10' 
UNION ALL SELECT '212-999-5555','2009-01-11';

WITH x AS
(
    SELECT
        [Date],
        wtn,
        part = DATEDIFF(DAY, 0, [Date]) 
        + DENSE_RANK() OVER
        (
            PARTITION BY wtn
            ORDER BY [Date] DESC
        )
    FROM @wtns
)
SELECT 
    WTN, 
    MinDate = MIN([Date]),
    MaxDate = MAX([Date])
FROM
    x
GROUP BY 
    part,
    WTN
ORDER BY
    WTN DESC,
    MaxDate;
8
ответ дан 7 December 2019 в 05:25
поделиться

Ваша проблема связана с ТИПАМИ ИНТЕРВАЛОВ и вещью под названием ПАКЕТНАЯ НОРМАЛЬНАЯ ФОРМА отношения.

Эти вопросы подробно обсуждаются в разделе " Временные данные и реляционная модель ».

Не ожидайте, что какая-либо система SQL действительно поможет вам с такими проблемами.

Несмотря на некоторые учебные системы, единственная СУБД, которая предлагает достойную поддержку для таких проблем, и о которой я знаю , мой собственный. Нет ссылки, потому что я не хочу делать здесь слишком много "затыкания".

0
ответ дан 7 December 2019 в 05:25
поделиться

Вы можете сделать это с помощью GROUP BY , определив границы:

WITH    Boundaries
      AS (
          SELECT    m.WTN
                   ,m.Date
                   ,CASE WHEN p.Date IS NULL THEN 1
                         ELSE 0
                    END AS IsStart
                   ,CASE WHEN n.Date IS NULL THEN 1
                         ELSE 0
                    END AS IsEnd
          FROM      so1590166 AS m
          LEFT JOIN so1590166 AS p
                    ON p.WTN = m.WTN
                       AND p.Date = DATEADD(d, -1, m.Date)
          LEFT JOIN so1590166 AS n
                    ON n.WTN = m.WTN
                       AND n.Date = DATEADD(d, 1, m.Date)
          WHERE     p.Date IS NULL
                    OR n.Date IS NULL
         )
SELECT  l.WTN
       ,l.Date AS MinDate
       ,MIN(r.Date) AS MaxDate
FROM    Boundaries l
INNER JOIN Boundaries r
        ON r.WTN = l.WTN
           AND r.Date >= l.Date
           AND l.IsStart = 1
           AND r.IsEnd = 1
GROUP BY l.WTN
       ,l.Date
0
ответ дан 7 December 2019 в 05:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: