Вход | Регистрация


1С:Предприятие ::

Метки: 

как в запросе найти дырку в последовательности чисел?

Я
   svird
 
13.12.17 - 18:36
Есть коды весовых товаров, оказывается весы имеют ограничение 5200 кодов. Вот автоматическая назначалка кодов уперлась в этот потолок. Что то мне не верится, что нету дырок, хочу переделать назначалку, что бы брала первый свободный код до 5200
 
  Рекламное место пустует
   Базис
 
1 - 13.12.17 - 18:38
Отсортируй и считай разницу. PLU не хватает? Дроби по отделам.
   Ёпрст
 
2 - 13.12.17 - 18:39
ну соедини с табличкой цифр и сгруппируй, там где Имеющие сумма =1 и есть "дырка"
   svird
 
3 - 13.12.17 - 18:42
(2) О хорошая идея.
(1) Про отделы спасибо, подумаем, хотя немного проблематично, так как весы одни или 2-я, а они ломаются часто. Ненадежная техника. И тогда используют одни.
   Михаил Козлов
 
4 - 13.12.17 - 18:43
(0) Перенумерация не подходит?
   svird
 
5 - 13.12.17 - 18:44
(4) Не это исключено, коды PLU не могут меняться.
А как можно создать табличку цифр если не использовать цикл?
   art commander
 
6 - 13.12.17 - 18:45
(0) Решать такого рода задачи запросом - извращение.
Но если уж очень хочется, тогда:
1 соединяешь таблицу с самой собой по условию т2.код<т1.код.
2. группируешь по т1.код и агрегируешь МАКСИМУМ(т2.код)
3. накладываешь условие т1.код-т2.код>1
   art commander
 
7 - 13.12.17 - 18:46
(5) выбрать 1
объединить
выбрать 2
объединить
выбрать 3...

и т.д.
   Михаил Козлов
 
8 - 13.12.17 - 18:53
Выгрузить в Эксель, добавить колонку с "правильным" кодом, прописать его последовательными значениями, посмотреть разницу.
   Ёпрст
 
9 - 13.12.17 - 18:54
   Ёпрст
 
10 - 13.12.17 - 18:55
Ну или так,

SELECT 
(a3.id + a2.id + a1.id + a0.id) КАК Числа

FROM
(
SELECT 1 id UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5 UNION ALL
SELECT 6 UNION ALL
SELECT 7 UNION ALL
SELECT 8 UNION ALL
SELECT 9
) as a0
INNER JOIN
(
SELECT 0 id UNION ALL
SELECT 10 UNION ALL
SELECT 20 UNION ALL
SELECT 30 UNION ALL
SELECT 40 UNION ALL
SELECT 50 UNION ALL
SELECT 60 UNION ALL
SELECT 70 UNION ALL
SELECT 80 UNION ALL
SELECT 90
) as a1 ON TRUE
INNER JOIN
(
SELECT 0 id UNION ALL
SELECT 100 UNION ALL
SELECT 200 UNION ALL
SELECT 300 UNION ALL
SELECT 400 UNION ALL
SELECT 500 UNION ALL
SELECT 600 UNION ALL
SELECT 700 UNION ALL
SELECT 800 UNION ALL
SELECT 900
) as a2 ON TRUE
INNER JOIN
(
SELECT 0 id UNION ALL
SELECT 1000 UNION ALL
SELECT 2000 UNION ALL
SELECT 3000 UNION ALL
SELECT 4000 UNION ALL
SELECT 5000 UNION ALL
SELECT 6000 UNION ALL
SELECT 7000 UNION ALL
SELECT 8000 UNION ALL
SELECT 9000
) as a3 ON TRUE
ORDER BY Числа
 
  Рекламное место пустует
   art commander
 
11 - 13.12.17 - 18:57
(10) А INNER JOIN зачем пишете?
   Жан Пердежон
 
12 - 13.12.17 - 18:59
(9) (10) фу
   Ёпрст
 
13 - 13.12.17 - 19:01
(11) да пофик, там обычный cross join
   Ёпрст
 
14 - 13.12.17 - 19:02
SELECT 
(a3.id + a2.id + a1.id + a0.id) КАК Числа

FROM
(
SELECT 1 id UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5 UNION ALL
SELECT 6 UNION ALL
SELECT 7 UNION ALL
SELECT 8 UNION ALL
SELECT 9
) as a0 ,
(
SELECT 0 id UNION ALL
SELECT 10 UNION ALL
SELECT 20 UNION ALL
SELECT 30 UNION ALL
SELECT 40 UNION ALL
SELECT 50 UNION ALL
SELECT 60 UNION ALL
SELECT 70 UNION ALL
SELECT 80 UNION ALL
SELECT 90
) as a1
,
(
SELECT 0 id UNION ALL
SELECT 100 UNION ALL
SELECT 200 UNION ALL
SELECT 300 UNION ALL
SELECT 400 UNION ALL
SELECT 500 UNION ALL
SELECT 600 UNION ALL
SELECT 700 UNION ALL
SELECT 800 UNION ALL
SELECT 900
) as a2  
,
(
SELECT 0 id UNION ALL
SELECT 1000 UNION ALL
SELECT 2000 UNION ALL
SELECT 3000 UNION ALL
SELECT 4000 UNION ALL
SELECT 5000 UNION ALL
SELECT 6000 UNION ALL
SELECT 7000 UNION ALL
SELECT 8000 UNION ALL
SELECT 9000
) as a3
ORDER BY Числа
   Ёпрст
 
15 - 13.12.17 - 19:03
(12) Предложи альтернативу.
   art commander
 
16 - 13.12.17 - 19:06
(15) В (6) альтернатива. Запрос будет в несколько раз короче, а работать при 5200 позициях все будут быстро.
   Ёпрст
 
17 - 13.12.17 - 19:10
(16) не понял, как при inner join + max, для таблицы из 2-х элементов по твоему алгоритму

1
10

ты найдешь 2,3,4,5,6,7,8,9 ?
   bolobol
 
18 - 13.12.17 - 19:34
(17) Ты наёдешь первую дырку, следующее число в которой  - свободно.
   Ёпрст
 
19 - 13.12.17 - 19:42
(18) задача то, все найти, насколько я понял, а не первую
   art commander
 
20 - 13.12.17 - 19:42
(19) "хочу переделать назначалку, что бы брала первый свободный код до 5200"
   Сияющий в темноте
 
21 - 13.12.17 - 20:05
какие у вас весы?
в весах есть записи 5200,а есть коды плу-их обычно 99999,т.к.на код 5 символов,если работатт в кодах,то нужно всего лишь,чтобы в весы грузились не более 5200 товаров,и в разные весы можно грузить разные товары
   Сияющий в темноте
 
22 - 13.12.17 - 20:07
а так,соединение таблицы сама с собой со смещкнием 1 и отсортировать по знаяению и выбрать первый,где значение второй соедмненной таблицы Null
   Ildarovich
 
23 - 13.12.17 - 21:04
Генерировать здесь таблицу чисел как предлагается в (2) совершенно не нужно, так же как и искать интервалы как предлагается в (6). Это существенно дольше и в данном случае совершенно излишне. Решать такие задачи запросом можно и нужно. Это гораздо быстрее, чем другими способами.

Поддержу (22), но с замечанием, что лучше не соединять, а объединять примерно как в в задаче 30 из http://catalog.mista.ru/public/460935/
ВЫБРАТЬ 
    Х, 
    ЛОЖЬ КАК Свободен
ПОМЕСТИТЬ ЧислаПлюс
ИЗ Числа
ОБЪЕДИНИТЬ
ВЫБРАТЬ    
    Х + 1, 
    ИСТИНА
ИЗ Числа
;
ВЫБРАТЬ ПЕРВЫЕ 1
    Х КАК ПервыйСвободныйАртикул
ИЗ ЧислаПлюс
СГРУППИРОВАТЬ ПО Х
ИМЕЮЩИЕ КОЛИЧЕСТВО(*) = 1 И МАКСИМУМ(Свободен) = ИСТИНА
Если коды строковые, а не числовые, то нужно взять из 30 все решение целиком, с преобразованием строк в числа.
   Сти
 
24 - 13.12.17 - 21:26
Коды числовые? Тогда вот:
ВЫБРАТЬ ПЕРВЫЕ 1
    Табличка1.Код + 1 КАК Код
ИЗ
    Табличка КАК Табличка1
        ЛЕВОЕ СОЕДИНЕНИЕ Табличка КАК Табличка2
        ПО (Табличка1.Код + 1 = Табличка2.Код)
ГДЕ
    Табличка2.Код ЕСТЬ NULL

   Сти
 
25 - 13.12.17 - 21:27
УПОРЯДОЧИТЬ ПО
    Табличка1.Код

   Ildarovich
 
26 - 13.12.17 - 21:36
(24) При отсутствии индекса по Код такое соединение приведет к перебору всех элементов "Табличка2" для каждого элемента "Табличка1". Значит, будет квадратичный рост. Если в табличке 10 000 элементов, то произведение уже 100 миллионов. Это уже больше сотни секунд - многовато для такой задачи. Решение (23) свободно от такого недостатка. В нем зависимость линейная. Выполнится за сотые-десятые доли секунды.
   Сти
 
27 - 13.12.17 - 21:41
(26) Согласен, без индекса будет долго. Но всякие коды чаще всего проиндексированы.
   Сияющий в темноте
 
28 - 13.12.17 - 22:15
(26) тогда выгружаем с индексированием во временную таблицу и радуемся
   Сияющий в темноте
 
29 - 13.12.17 - 22:16
хотя,перебор все равно светит,поэтому просто перебираем ьаблицу и ищем первую ячейку,где код не соответствует номеру
   Сти
 
30 - 13.12.17 - 22:30
Ради интереса запилил тестовую обработку, 10000 строк, ну и замер производительности на моем тарантасе:

Без индексирования в цикле 10 раз (больше не рискнул из-за 100 млн.):
23 за 0,764693 сек,
24 за 26,450973 сек - ожидаемо долго.

Первый вариант рвет мой на мелкие части )

С индексированием в цикле 1000 раз:
23 за 28,047738 сек
24 за 2,526163 сек

А вот тут индексы уже рулят, вариант в 23 проигрывает из за группировки и поиска максимумов.
   Ildarovich
 
31 - 13.12.17 - 22:51
(30) в (22) была неточность, попробуйте ОБЪЕДИНИТЬ ВСЕ и без временной таблицы. Вот в таком виде:
;
ВЫБРАТЬ ПЕРВЫЕ 1
    Х КАК ПервыйСвободныйАртикул
ИЗ (ВЫБРАТЬ 
    Х, 
    ЛОЖЬ КАК Свободен
ИЗ Числа
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ    
    Х + 1, 
    ИСТИНА
ИЗ Числа) КАК ВложенныйЗапрос
СГРУППИРОВАТЬ ПО Х
ИМЕЮЩИЕ КОЛИЧЕСТВО(*) = 1 И МАКСИМУМ(Свободен) = ИСТИНА
Проигрыш должен быть, но не такой существенный. Похоже больше не на потери на вычислениях, а на потери времени на запись временной таблицы.
   Ildarovich
 
32 - 13.12.17 - 23:26
Есть еще вариант
ВЫБРАТЬ ПЕРВЫЕ 1
    Дано.Х + ВЗ.У КАК Х
ИЗ
    Дано КАК Дано,
    (ВЫБРАТЬ
        0 КАК У    
    ОБЪЕДИНИТЬ
    ВЫБРАТЬ
        1) КАК ВЗ
СГРУППИРОВАТЬ ПО
    Дано.Х + ВЗ.У
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(*) = 1 И
    МИНИМУМ(ВЗ.У) = 1
УПОРЯДОЧИТЬ ПО
    Дано.Х + ВЗ.У

   Ildarovich
 
33 - 13.12.17 - 23:59
+(32) А можно еще ВЫБРАТЬ ПЕРВЫЕ 2 и МИНИМУМ(ВЗ.У) = 1 не проверять. В общем, простор для исследований есть))
 
  Рекламное место пустует
   PCcomCat
 
34 - 14.12.17 - 00:35
(33) Пока Вы здесь... ))
На сколько криво так писать? - на листике накидано по-быстренькому:

"ВЫБРАТЬ
Справ.Код
ПОМЕСТИТЬ Справ
ИЗ
 Справочник.НекийСправочник КАК Справ
;
Выбрать
 Справ1.Код,
 ЕСТЬNULL(Справ2.Код, Справ1.Код) КАК КодПредыдущий
ИЗ
 Справ КАК Справ1
 ЛЕВОЕ СОЕДИНЕНИЕ Справ КАК Справ2
   ПО Справ2.Код В 
      (ВЫБРАТЬ//* можно ПЕРВЫЕ 1 без МАКСИМУМ, при этом УПОРЯДОЧИТЬ ПО СправПров.Код УБЫВ *//

         МАКСИМУМ(СправПров.Код)
       ИЗ 
         Справ КАК СправПров
       ГДЕ
         СправПров.Код < Справ1.Код)
ГДЕ
 Справ1.Код - ЕСТЬNULL(Справ2.Код, Справ1.Код)>1
;
УНИЧТОЖИТЬ Справ"
   Ildarovich
 
35 - 14.12.17 - 00:55
(34) Это кореллированный запрос. В условиях соединения его использовать не рекомендуется. Если индекс по полю код есть, то можно робко надеяться на хороший план запроса, где агрегатная функция будет браться из индекса и соединение будет на него же опираться, но гораздо чаще бывает по другому. В файловой базе и Postgre точно будут тормоза, а в MSSQL возможно будут. Я бы не рисковал, если есть более надежные способы.
   PCcomCat
 
36 - 14.12.17 - 01:09
(35) Спасибо!
   Сти
 
37 - 14.12.17 - 16:32
(31) Проверил
31 за 11,609783 сек 
24 за 1,627492 сек 

ну, это один из результатов, гонял несколько раз, порядок значений тот же.

Но 31 действительно надежнее в любых условиях, да и пользователь при интерактивной работе разницы не заметит.
   Ildarovich
 
38 - 14.12.17 - 17:10
(37) Спасибо, согласен, но раз "пошла такая пьянка", не проверите еще (32)+(33). Там другой подход. Лучше в виде:
ВЫБРАТЬ ПЕРВЫЕ 2
    Дано.Х + ВЗ.У КАК Х
ИЗ
    Дано КАК Дано,
    (ВЫБРАТЬ
        0 КАК У    
    ОБЪЕДИНИТЬ
    ВЫБРАТЬ
        1) КАК ВЗ
СГРУППИРОВАТЬ ПО
    Дано.Х + ВЗ.У
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(*) = 1
УПОРЯДОЧИТЬ ПО
    Дано.Х + ВЗ.У

   Сти
 
39 - 15.12.17 - 11:06
(38)
В цикле 1000 раз:

32 13,264319
33 16,620937 - интересно тем, что выдает диапазон кодов, между которым есть пропуски, т.е. последний имеющийся до и первый после пропуска. Части ПОМЕСТИТЬ и УНИЧТОЖИТЬ из запроса выбросил, так как на вход всех тестируемых запросов и так подается ранее сформированная тестовая табличка с кодами, т.е. осталась только работающая часть запроса.
37 11,977468 - в первой строке всегда 0, во второй нужное значение
   Ildarovich
 
40 - 15.12.17 - 13:41
(39) Большое спасибо!



Список тем форума
  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.
Тема не обновлялась длительное время, и была помечена как архивная. Добавление сообщений невозможно.
Но вы можете создать новую ветку и вам обязательно ответят!
Каждый час на Волшебном форуме бывает более 2000 человек.
Рекламное место пустует