SQL Server 2008 Предыдущая строка извлечения - PullRequest
0 голосов
/ 19 марта 2012

У меня есть строки, подобные приведенным ниже в столбце SQL. Я хочу извлечь их как совокупную сумму в гигабайтах. Пример:

Original Column ---------> Expected Output from a TSQL function
-------------------------------------------
$15 / 1GB 24m + Intern 120MB ----------> 1.12 GB
$19.95 / 500MB + $49.95 / 9GB Blackberry -----> 9.5GB
$174.95 Blackberry 24GB + $10 / 1GB Datapack ----> 25GB
$79 / 6GB --> 6GB
Null --> Null
$20 Plan --> 0GB

Примечание: для наших целей 1000 МБ = 1 ГБ (не 1024).

Шаблон представляет собой числа, за которыми следуют ГБ / МБ, обычно они объединяются как 1 ГБ (без пробела, но иногда могут содержать пробел, это не особенно важно, если трудно реализовать для этого исключения).

Иногда в одной и той же строке может быть до трех или четырех экземпляров ГБ / МБ, которые обычно разделяются знаком + (см. Строки 2 и 3 моего примера выше).

Я видел, как мы извлекаем значения в долларах в одном из ответов, где за числами следует $, или извлекаем все целые числа в строке, но я не хочу извлекать значения в долларах или все целые числа в строке. Я просто хочу сумму ГБ / МБ в строке.

1 Ответ

2 голосов
/ 19 марта 2012

Следующее может показаться несколько конкретным и слишком предположительным, даже если это может показаться слишком сложным для конкретного и чрезмерно предполагаемого решения.Тем не менее, я надеюсь, что это, по крайней мере, послужит хорошей отправной точкой.

Вот предположения, которые я должен был сделать, чтобы избежать дальнейшего усложнения сценария:

  1. Значениядля извлечения никогда не должно содержать десятичной точки (являются целыми числами).

  2. Извлекаемым значениям всегда предшествует пробел или начало столбца.

  3. Ни GB, ни MB не могут быть частью чего-либо, кроме объема трафика (значение, которое будет извлечено).

  4. Ни GB ни MB никогда не предшествует пробел.

  5. Все строки либо уникальны, либо сопровождаются другим столбцом или столбцами, которые могут использоваться в качестве ключевых значений.(Мое решение, в частности, использует дополнительный столбец в качестве ключа.)

Итак, вот моя попытка (которая вернула ожидаемые результаты для всех данных образца, представленных в исходном сообщении):

WITH data (id, str) AS (
             SELECT 1, '$15 / 1GB 24m + Intern 120MB' ----------> 1.12 GB
  UNION ALL  SELECT 2, '$19.95 / 500MB + $49.95 / 9GB Blackberry' -----> 9.5GB
  UNION ALL  SELECT 3, '$174.95 Blackberry 24GB + $10 / 1GB Datapack' ----> 25GB
  UNION ALL  SELECT 4, '$79 / 6GB' --> 6GB
  UNION ALL  SELECT 5, Null --> Null
  UNION ALL  SELECT 6, '$20 Plan' --> 0GB
  UNION ALL  SELECT 7, '460MB' --> 0.46GB
),
unified AS (
  SELECT
    id,
    oldstr = str,
    str = REPLACE(str, 'GB', '000MB')
  FROM data
),
split AS (
  SELECT
    id,
    ofs    = 0,
    endpos = CHARINDEX('MB', str),
    length = ISNULL(CHARINDEX(' ', REVERSE(SUBSTRING(str, 1, NULLIF(CHARINDEX('MB', str), 0) - 1)) + ' ') - 1, 0),
    str    = SUBSTRING(str, NULLIF(CHARINDEX('MB', str), 0) + 2, 999999)
  FROM unified
  UNION ALL
  SELECT
    id,
    ofs    = NULLIF(endpos, 0) + 1,
    endpos = CHARINDEX('MB', str),
    length = ISNULL(CHARINDEX(' ', REVERSE(SUBSTRING(str, 1, NULLIF(CHARINDEX('MB', str), 0) - 1)) + ' ') - 1, 0),
    str    = SUBSTRING(str, NULLIF(CHARINDEX('MB', str), 0) + 2, 999999)
  FROM split
  WHERE length > 0
),
extracted AS (
  SELECT
    d.id,
    str = d.oldstr,
    mb = CAST(SUBSTRING(d.str, s.ofs + s.endpos - s.length, s.length) AS int)
  FROM unified d
  INNER JOIN split s ON d.id = s.id
)
SELECT
  id,
  str,
  gb = RTRIM(CAST(SUM(mb) AS float) / 1000) + 'GB'
FROM extracted
GROUP BY id, str
ORDER BY id

По сути, идея состоит в том, чтобы сначала преобразовать все гигабайты в мегабайты, чтобы затем иметь возможность поиска и извлечения только мегабайтных объемов.Метод поиска и извлечения включает рекурсивный CTE и состоит по существу из следующих шагов:

1) найти позицию первого MB;

2) найти длину числа непосредственно передMB;

3) обрезать начало строки прямо в конце первого MB;

4) повтора с шага 1 до тех пор, пока не будет найдено MB;

5) соединить найденные цифры с исходным списком строк, чтобы извлечь сами суммы.

После этого нам остается только сгруппировать по ключевым значениям и суммировать полученные суммы.Вот вывод:

id  str                                           gb
--  --------------------------------------------  ------
1   $15 / 1GB 24m + Intern 120MB                  1.12GB
2   $19.95 / 500MB + $49.95 / 9GB Blackberry      9.5GB
3   $174.95 Blackberry 24GB + $10 / 1GB Datapack  25GB
4   $79 / 6GB                                     6GB
5   NULL                                          NULL
6   $20 Plan                                      0GB
7   460MB                                         0.46GB
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...