MySQL: использование вычисляемого столбца счетчика в качестве ключа для подзапроса - PullRequest
0 голосов
/ 28 мая 2019

Извините, длинная предыстория, но нужно уточнить вопрос.

В моей организации у компьютеров есть имена вроде CNT30[0-9]{3}[1-9a-z], например cnt300021 или cnt30253a.

Последний символ является «классификатором», поэтому одному рабочему месту могут быть присвоены компьютеры с одинаковыми именами, различаемые этим классификатором. Например, cnt300021 может означать настольный компьютер на рабочем месте # 002, а cnt30002a может означать ноутбук, назначенный для того же рабочего места. Рабочие места являются «виртуальными», и их существование создано исключительно для нашего удобства (ИТ-отдел).

Каждый отдел имеет свой уникальный диапазон [0-9]{3}. Например, компьютеры учета имеют имена, начинающиеся с cnt302751 до cnt30299z, что дает им максимум 25 уникальных рабочих мест, до 35 компьютеров на одно рабочее место. (Большинство пользователей IRL имеют один настольный ПК, гораздо меньше - настольный компьютер и ноутбук, и только 2 или 3 технических специалиста имеют в своем распоряжении более одного ноутбука).

Недавно, проводя инвентаризацию паспортов компьютеров (не уверен насчет термина: бумага, которая означает для компьютера то же самое, что означает паспорт для человека), Я обнаружил, что в последовательных дырах есть некоторые дыры нумерация. Например, у нас есть cnt302531 и cnt302551, но нет cnt302541, что означает, что нет рабочего места # 254.

Что я хочу сделать? Я хочу найти эти пробелы без ручного поиска. Для этого мне нужен цикл от 1 до MaxComp=664 (больше рабочих мест не назначено)

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

for a=0 to MaxComp
  a$="CNT30"+right(a+1000,3)
'comparing only 8 leftmost characters, ignoring 9th one - the qualifier
  b$=(select name from table where left(name,8) like a$)
  print a$;b$
next a

Этот код должен дать мне два столбца: возможные имена и существующие.

Но я не могу понять, как реализовать это в SQL-запросе. Что я пробовал:

# because of qualifier there may be several computers with same
# 8 leftmost characters
select @cnum:=@cnum+1 as CompNum, group_concat(name separator ',')
# PCs are inventoried by OCS-NG Inventory software
  from hardware
  cross join (select @cnum:=0) cnt
  where left(hardware.name,8)=concat('CNT30',right(@cnum+1000,3))
  limit 100

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

1 Ответ

0 голосов
/ 28 мая 2019

Найден рабочий путь:

(сначала я пытался использовать хранимую функцию)

CREATE FUNCTION `count_comps`(num smallint) RETURNS tinytext CHARSET utf8
BEGIN
    return (select group_concat(name separator ',')
        from hardware where left(hardware.name,8)=concat('CNT30',right(num+1000,3))
        );
END

Затем я изо всех сил пытался воспроизвести результаты функции в подзапросе.И я сделал это!Примечание: внутренний выбор возвращает те же результаты, что и функция

# Starting point. May be INcreased to narrow the results list
set @cnum:=0;
select
    @cnum:=@cnum+1 as CompNum,
    concat('CNT30',right(@cnum+1000,3)) as CalcNum,
# this
    count_comps(@cnum) as hwns,
# and this gives equal results
    (select group_concat(name separator ',')
        from hardware where left(name,8)=calcnum
        ) hwn2
    from hardware
# no more dummy tables here
# Ending point. May be DEcreased to narrow the results list
  where @cnum<665;

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

Пример частичных результатов (начиная с set @cnum:=479;, заканчивая where @cnum<530;):

CompNum, CalcNum, hwns, hwn2 '488', 'CNT30488', 'CNT304881', 'CNT304881' '489', 'CNT30489', 'CNT304892', 'CNT304892' '490', 'CNT30490', 'CNT304901,CNT304902,CNT304903', CNT304901,CNT304902,CNT304903' '491', 'CNT30491', NULL, NULL '492', 'CNT30492', NULL, NULL '493', 'CNT30493', 'CNT304932', 'CNT304932' '494', 'CNT30494', 'CNT304941', 'CNT304941'

Я обнаружил, что нет рабочих мест # 491 и # 492.При следующем добавлении компьютеров для отдела «Октябрьский регион» (диапазон 480–529), как минимум, два новых компьютера получат имена CNT304911 и CNT304921, заполняя этот пробел.

...