Используя TSQL, как я могу определить, является ли мой CHAR последним в последовательности? Кроме того, что, если последовательность букв «переворачивается» с «z» на «a»? - PullRequest
1 голос
/ 02 июня 2009

Допустим, у меня есть следующая таблица в SQL Server 2005:

id | Date | Letter
-----------------------------
01 | 5/1/2009 | W
02 | 5/1/2009 | X
03 | 5/1/2009 | Y
04 | 5/1/2009 | Z
05 | 5/1/2009 | A
06 | 5/1/2009 | B
07 | 5/1/2009 | D
08 | 5/1/2009 | E
09 | 5/2/2009 | W
10 | 5/2/2009 | X
11 | 5/2/2009 | Y
12 | 5/2/2009 | Z
13 | 5/2/2009 | A
14 | 5/2/2009 | B
15 | 5/2/2009 | C
16 | 5/2/2009 | D
17 | 5/3/2009 | W
18 | 5/3/2009 | X

В моем предыдущем вопросе я спросил, как определить, какая последовательность букв отсутствовала. В моем примере это будет буква C между строками 6 и 7. Я получил следующий ответ, и он работает по большей части:

SELECT * from TABLE1 t1 
LEFT OUTER JOIN TABLE2 t2 
  ON ASCII(t2.INTCol) - 1 = ASCII(t2.INTCol) 
  AND t1.date = t2.date
  WHERE t2.id IS NULL

Однако у этого решения есть две проблемы. Он вернет ложные срабатывания в двух случаях.

  1. Последовательность букв начинается каждый день с буквы «W». Итак, я получаю ложноположительный результат для последней записи каждого дня. Это были бы строки 8 и 16 в моих данных примера.

  2. Поскольку последовательность начинается каждый день с 'W', я получаю ложное срабатывание для записи 'Z', потому что ('Z' + 1) дает мне '[', а не 'A'.

Для # 2, я полагаю, я могу вставить утверждение «IF», ​​которое говорит: «Если это Z, ищите A», но я открыт для любых «более чистых» решений.

Я действительно понятия не имею, как сделать # 1, поэтому я действительно ищу помощь по этому вопросу. EDIT: Что-то, что я пропустил, выполнение MAX (t1.id) не сработает, поскольку строки не всегда вставляются в последовательности. На самом деле, глядя на мои данные, они всегда вставляются в порядке [a-z], хотя первая запись - «w». Я знаю, что это неубедительно, но я имею дело с файлами журналов от телефонных коммутаторов за десятки миллионов долларов. Я мало что могу с этим поделать.

Ответы [ 3 ]

1 голос
/ 02 июня 2009

Как это?

SELECT * FROM 
(
SELECT CASE
  WHEN t1.date = t2.date
    AND (ASCII(t2.IntCol) = 90 AND ASCII(t1.IntCol) <> 65)
     THEN 1
  WHEN t1.date = t2.date
    AND ASCII(t2.IntCol) <> ASCII(t1.IntCol) + 1
     THEN 1
  ELSE 0
END AS IsMissing, t1.*

from TABLE1 t1 
LEFT OUTER JOIN TABLE1 t2   
  ON t1.id +1 = t2.id
) as a WHERE a.IsMissing = 1
1 голос
/ 02 июня 2009

Ролловер: используйте мод.

Дни: добавьте предикат, исключающий окончательную запись каждого дня.

create view missing_letter as 
SELECT *  from TABLE1 t1 
LEFT OUTER JOIN TABLE2 t2 
  ON t1.id = t2.id 
  AND t1.date = t2.date
  and mod( ascii(t1.letter) - ascii('A'), ascii('Z') + 1 ) 
  <> mod( ascii(t2.letter) - ascii('A'), ascii('Z') + 1 ) - 1 
  and t1.id < (select max(t3.id) from table t3 where t3.date = t1.date)
;

Лучшим решением было бы придумать вспомогательную таблицу упорядоченных разрешенных букв и найти все буквы в этой вспомогательной таблице, которые отсутствуют ("... где не существует ..."), где любая из этих букв предшествует самой высокой букве в вашей таблице.

0 голосов
/ 02 июня 2009

Глядя на данные, вы можете сделать MAX для ID для каждой строки, чтобы получить последний символ в последовательности.

Если нет записей, вы можете вставить W
Если Z, то вставить A
Еще добавить символ после текущего символа

Это то, что вы ищете?

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