Логическая группировка SQL Server за последнее время - PullRequest
3 голосов
/ 22 марта 2011

Я ищу лучший подход к этому вопросу, и пока мне не повезло.Я использую Microsoft SQL Server 2008.

Итак, вот пример данных пользователя:

=====================

Имя Статус Дата

============================ *

BOB Active 2011-03-07

БОБ активен 2011-03-11

БОБ отключен 2011-03-15

БОБ отключен 2011-03-21

БОБ активен 2011-03-23 ​​

ЛПП Актив 2011-03-28

=====================

Я хочу, чтобы это было сгруппировано так, чтобы оно показывало, когда пользователь фактически изменил статус, а не в следующий раз, когда они были проверены, если результат остался прежним, так что запрос будет выглядеть следующим образом:

======================

BOB Active 2011-03-07

BOB отключен 2011-03-15

ЛПП Активный 2011-03-23 ​​

======================

Это данные, которые я не делаюесть какой-нибудь доступ к тому, как он создается.

Есть идеи о том, как лучше всего получить эти данные так, как мне нужно?Имейте в виду, что это для тысяч записей, и производительность следует принимать во внимание, если это возможно.Я не могу придумать способ сделать группировку так, чтобы она не сгруппировала «Активировать» вместе и не использовала бы агрегатную функцию MIN.

Есть ли способ выполнить цикл и заставить данные выглядетькак это для группировки и группы в последнем столбце?Будет ли это даже лучшим подходом?

======================

Имя Статус Дата Группа

======================

BOB Active 2011-03-07 1

BOB Active 2011-03-11 1

BOB отключен 2011-03-15 2

BOB отключен 2011-03-21 2

BOB активен 2011-03-23 ​​3

BOB Active 2011-03-28 3

====================== * 10= *

Все мои поиски не сработали, если бы кто-то мог дать мне ключевое слово для поиска, чтобы получить меня на правильном пути, который был бы очень признателен.

Ответы [ 2 ]

1 голос
/ 22 марта 2011
select tb.name,tb.status,tb.date 
from the_table tb
join (select name,min(date) as date from the_table group by name) t_aggr on tb.name=t_aggr.name and tb.date=t_aggr.date
union
select tb2.name,tb2.status,tb2.date
from the_table tb1
join the_table tb2 on tb1.name=tb2.name and tb1.status<>tb2.status and tb2.date>tb1.date
left join the_table tb3 on tb1.name=tb2.name and tb1.date<tb3.date and tb3.date<tb2.date
where tb3.date is null

Первый выбор в объединении - получить первую запись. Второй должен получить изменения. В любом случае протестируйте его, так как у меня нет сервера sql, чтобы попробовать его.

0 голосов
/ 22 марта 2011

Если вы используете SQL Server 2005 или более новую версию (которой вы являетесь!), Вы можете легко обнаруживать изменения в статусе, ранжируя даты и присоединяясь к предыдущей дате. Это даст вам то, что вам нужно:

WITH rankedDates AS (
    SELECT name, status, date, row_number() OVER (PARTITION BY name ORDER BY DATE) as dateRank
    FROM #myTable
)
SELECT curr.name, curr.status, curr.date
FROM rankedDates curr
LEFT JOIN rankedDates prev
    ON curr.name = prev.name
    AND curr.dateRank = prev.dateRank+1
WHERE prev.status IS NULL
    OR curr.status <> prev.status

Несколько sql для создания тестовых данных, которые я использовал для создания этой функции (я бросил Джейка, чтобы убедиться, что он обрабатывает двух человек в порядке):

SELECT 'BOB' AS name, 'Active' AS status, '2011-03-07' AS date  
INTO #myTable
UNION ALL
SELECT 'BOB', 'Active', '2011-03-11' UNION ALL
SELECT 'BOB', 'Disabled', '2011-03-15' UNION ALL
SELECT 'BOB', 'Disabled', '2011-03-21' UNION ALL
SELECT 'BOB', 'Active', '2011-03-23' UNION ALL
SELECT 'BOB', 'Active', '2011-03-28' 
--include below lines for more complex example
UNION ALL
SELECT 'JAKE', 'Active', '2011-01-11' UNION ALL
SELECT 'JAKE', 'Disabled', '2011-01-15' UNION ALL
SELECT 'JAKE', 'Disabled', '2011-05-21' UNION ALL
SELECT 'JAKE', 'Active', '2011-05-23' UNION ALL
SELECT 'JAKE', 'Active', '2011-07-28'

Что касается производительности, было бы лучше, если бы у вас были идентификаторы для имени и индекс имени, а также для даты.

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