Фильтрация неверных данных в SQL Server 2005 - PullRequest
4 голосов
/ 24 июня 2010

Использование SQL Server 2005

У меня есть таблица со следующими столбцами

значение имени имени даты

Я хочу выбрать все строки в таблице, где естьне четыре последовательных нуля по дате.Как бы я это сделал?Ниже приведен пример того, что я имею в виду.

id      name     date         value
1       a        1/1/2010     5
2       a        1/2/2010     3
3       a        1/3/2010     5
4       a        1/4/2010     0
5       a        1/7/2010     0
6       a        1/8/2010     0
7       a        1/9/2010     2
8       a        1/10/2010    3
9       a        1/11/2010    0
10      a        1/15/2010    0
11      a        1/16/2010    0
12      a        1/17/2010    0
13      a        1/20/2010    4
14      a        1/21/2010    4

Я бы хотел, чтобы результат запроса включал все строки, кроме идентификатора 9-12.

Ответы [ 3 ]

2 голосов
/ 24 июня 2010

Предполагается, что вы упорядочили строки по идентификатору, но вы можете просто заменить ORDER BY id на что-то другое, и оно все равно должно работать.

Использование T-SQL CTE, найденного в этой Kodyaz DevelopmentРесурсы сайта Мне удалось создать приведенный ниже код.У меня это работает, поэтому он удаляет строки, где есть два последовательных нуля, а не 4, так как я протестировал его в своем коде и просто изменил имена таблиц / строк.

WITH CTE as (
  SELECT
    RN = ROW_NUMBER() OVER (ORDER BY id),
    *
  FROM tablename
)
SELECT
  [Current Row].*
FROM CTE [Current Row]
LEFT JOIN CTE [Previous Row] ON
  [Previous Row].RN = [Current Row].RN - 1
LEFT JOIN CTE [Next Row] ON
  [Next Row].RN = [Current Row].RN + 1
WHERE
  not([Current Row].value = 0 AND [Next Row].value = 0) AND  
     // this deletes the row where value is zero and the next rows value is zero
  not([Previous Row].value = 0 AND [Current Row].value = 0) 
     // this deletes the row where value is zero and the previous rows value is zero

Все, что вам нужно сделать, чтобыСделайте так, чтобы ваше дело включало каждую возможную комбинацию в оператор WHERE.Например, работа с этой строкой и тремя следующими строками, равными 0, ИЛИ эта строка с предыдущей и двумя последующими строками.

1 голос
/ 24 июня 2010

Вы не упоминаете, как имя используется, поэтому я предполагаю, что вы хотите, чтобы это было сделано по имени. Я собираюсь далее предположить, что когда вы говорите о «последовательном», то вы имеете в виду в порядке дат, а не в порядке идентификаторов. Наконец, я также предполагаю, что вы также исключили бы 5 нулей подряд, 6 нулей подряд и т. Д.

Там может быть более простой способ, но это должно работать:

;WITH Transitions_To_CTE AS
(
    SELECT
        T1.id,
        T1.name,
        T1.date,
        T1.value
    FROM
        My_Table T1
    LEFT OUTER JOIN My_Table T2 ON
        T2.name = T1.name AND
        T2.date < T1.date AND
        T2.value <> 0
    LEFT OUTER JOIN My_Table T3 ON
        T3.name = T1.name AND
        T3.date > COALESCE(T2.date, '1900-01-01') AND
        T3.date < T1.date
    WHERE
        T1.value = 0 AND
        T3.id IS NULL
),
Transitions_From_CTE AS
(
    SELECT
        T1.id,
        T1.name,
        T1.date,
        T1.value
    FROM
        My_Table T1
    LEFT OUTER JOIN My_Table T2 ON
        T2.name = T1.name AND
        T2.date > T1.date AND
        T2.value <> 0
    LEFT OUTER JOIN My_Table T3 ON
        T3.name = T1.name AND
        T3.date < COALESCE(T2.date, '9999-12-31') AND
        T3.date > T1.date
    WHERE
        T1.value = 0 AND
        T3.id IS NULL
),
Range_Exclusions AS
(
    SELECT
        S.name,
        S.date AS start_date,
        E.date AS end_date
    FROM
        Transitions_To_CTE S
    INNER JOIN Transitions_From_CTE E ON
        E.name = S.name AND
        E.date > S.date
    LEFT OUTER JOIN Transitions_From_CTE E2 ON
        E2.name = S.name AND
        E2.date > S.date AND
        E2.date < E.date
    WHERE
        E2.id IS NULL AND
        (SELECT COUNT(*) FROM dbo.My_Table T WHERE T.name = S.name AND T.date BETWEEN S.date AND E.date) >= 4
)
SELECT
    T.id,
    T.name,
    T.date,
    T.value
FROM
    dbo.My_Table T
WHERE
    NOT EXISTS (SELECT * FROM Range_Exclusions RE WHERE RE.name = T.name AND T.date BETWEEN RE.start_date AND RE.end_date)
0 голосов
/ 24 июня 2010

Вот моя попытка: использовать рекурсивный cte для определения количества последовательных нулей, затем создать последовательность идентификаторов, используя уровень> 4, а затем просто выполнить предложение in in для идентификаторов.

with trend --work out number of consecutive zeros using level
as
(Select 1 as level, id, value, id as startid
    from IdsAndValues
    Union All
    Select [Level]+1, P.ID, p.value, t.startid
    From IdsAndValues as p
        Inner Join trend as t on p.id = t.id+1
    Where t.value =0 and p.value=0
)
,IDs --create sequence of ids using startid and  id, this allows us to do the not in
as
(   
    Select  startid as ExcludeID ,id 
    from trend as t--
    Where level>=4
    Union All
    Select ExcludeID +1, id
    From ids 
    where ExcludeID <id 
)

Select *
from IdsAndValues
Where id Not in
    (Select ExcludeID from IDs)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...