1. SQL / Говнокод #16819

    −120

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    CREATE TABLE `numbers` (
      `number` BIGINT(20) DEFAULT NULL
    ) ENGINE=InnoDB;
    
    CREATE TABLE `numbers_small` (
      `number` INT(11) DEFAULT NULL
    ) ENGINE=InnoDB;
    
     -- numbers
    
    INSERT INTO `numbers` (`number`) VALUES('0');
    INSERT INTO `numbers` (`number`) VALUES('1000');
    INSERT INTO `numbers` (`number`) VALUES('2000');
    INSERT INTO `numbers` (`number`) VALUES('3000');
    INSERT INTO `numbers` (`number`) VALUES('4000');
    INSERT INTO `numbers` (`number`) VALUES('5000');
    
    -- 10 000 lines of inserting numbers into table numbers
    -- ...
    INSERT INTO `numbers` (`number`) VALUES('5999');
    INSERT INTO `numbers` (`number`) VALUES('6999');
    INSERT INTO `numbers` (`number`) VALUES('7999');
    INSERT INTO `numbers` (`number`) VALUES('8999');
    INSERT INTO `numbers` (`number`) VALUES('9999');
    
    -- numbers small
    
    INSERT INTO `numbers_small` (`number`) VALUES('0');
    INSERT INTO `numbers_small` (`number`) VALUES('1');
    INSERT INTO `numbers_small` (`number`) VALUES('2');
    INSERT INTO `numbers_small` (`number`) VALUES('3');
    INSERT INTO `numbers_small` (`number`) VALUES('4');
    INSERT INTO `numbers_small` (`number`) VALUES('5');
    INSERT INTO `numbers_small` (`number`) VALUES('6');
    INSERT INTO `numbers_small` (`number`) VALUES('7');
    INSERT INTO `numbers_small` (`number`) VALUES('8');
    INSERT INTO `numbers_small` (`number`) VALUES('9');

    Сделали нам программу на java. Прислали скрипт для обновления базы данных DatabaseUpdateScript.sql на 874 KB.

    Запостил: ftr, 08 Октября 2014

    Комментарии (39) RSS

    • мб было условие что нужно обновлять программу тока через sql? :-D
      Ответить
      • Ну тут еще другой, более напрашивающийся вопрос: зачем нужны таблицы заполненые просто целыми числами? Я как ни стараюсь, не могу придумать применения.
        Ответить
    • Что делать, если мне понадобятся большие числа? :)
      Ответить
    • Друг прокомментировал: "generate_series потомушто нету".
      Ответить
    • интересно, что помешало им написать запрос, который генерит 10 000 чисел?
      Ответить
      • generate_series потомушто нету

        Или все же в мускуле есть какой-то аналог?

        P.S. Стековерфловочка подсказывает, что нету.
        Ответить
        • я не знаю как в мускуле, но в mssql можно написать примерно так
          select top 10000
          	row_number() over(order by o1.object_id) as x
          from sys.objects as o1
          cross join sys.objects as o2
          cross join sys.objects as o3
          cross join sys.objects as o4
          cross join sys.objects as o5
          cross join sys.objects as o6
          Ответить
          • Мда. postgresql:
            select generate_series(1, 10000);
            P.S. А если в sys.objects будет дофига записей, у m$$ql крышу не снесет от такого джойна?
            Ответить
            • какой то микрософтовский ад
              select level from dual connect by level <= 10000;
              пытался найти что в m$ с иерархическими запросами, оказалось всё печально, какие то union all, какая то неочевидная переголова
              так сложно было подсмотреть, что сделано у взрослых?..

              > select generate_series(1, 10000);
              видимо select * from generate_series(1, 10000) ?
              Ответить
              • честно говоря не вижу ничего сложного.
                ;with tbl
                (
                select 1 as x from blablabla
                union all
                select x + 1 from tbl
                );

                первый запрос определяется так сказать init запрос.
                далее, делаем union all то CTE, в котором она используется, т.е. tbl. и все, этот union all будет добавляется, пока хотя бы одна строка возвращается во втором запросе.
                например вот
                with data 
                as(
                	select DictionaryId,
                		ParentId,
                		DictionaryName,
                		cast(DictionaryName as nvarchar(1000)) as HierarchialName
                	from Warehouse.Dictionary
                	where ParentId is null
                		and TypeId in (select TypeId from Warehouse.HistoryDictionaries)
                
                	union all
                
                	select
                		d.DictionaryId,
                		d.ParentId,
                		d.DictionaryName,
                		cast(t.HierarchialName + ', ' + d.DictionaryName as nvarchar(1000)) as HierarchicalName
                	from Warehouse.Dictionary as d
                	join data as t
                		on d.ParentId = t.DictionaryId
                )
                select *
                from data

                и кстати, у меня этот запрос вернул 11к строк за 1 секунду, когда
                select level from dual connect by level <= 10000;
                на этой же сервере (да, на одной виртуальке крутятся mssql и oracle) отработал за 2 секунды
                Ответить
                • > например вот
                  то ли дело условия выборки корневых значений и всю вторую половину запроса заменить на start with + connect by
                  впрочем, оракловый sys_connect_by_path сам не без изъяна (хорошо хоть нужен редко)
                  Ответить
              • > видимо select * from generate_series(1, 10000) ?
                Ага. Вот только интересно, почему оно работает и без from... В доке ничего не написано о той форме записи, которую я сдуру по памяти привёл:
                -- так пашет
                postgres=# select generate_series(1, 3) as x, generate_series(5, 7) as y;
                 x | y 
                ---+---
                 1 | 5
                 2 | 6
                 3 | 7
                -- и так тоже пашет
                postgres=# select * from generate_series(1, 2) x, generate_series(5, 6) y;
                 x | y 
                ---+---
                 1 | 5
                 1 | 6
                 2 | 5
                 2 | 6
                Ответить
                • > select generate_series(1, 3) as x, generate_series(5, 7) as y;
                  вот это прикольно, конечно
                  хоть и неожиданно
                  если разной длины колонки будут - недостающие значения будут, видимо, null?
                  Ответить
                  • > если разной длины колонки будут - недостающие значения будут, видимо, null?
                    Авотхуй! Получается наименьшее общее кратное от количества записей в каждой серии. Довольно странная фича, и недокументированная.
                    Ответить
                  • А если написать вот так: select *, generate_series(1, 3) from test, то получится как и при select * from generate_series(1, 3) s, test - по 3 записи на каждую запись в табличке.

                    P.S. Есть вероятность, что это какая-то общая фишка для функций, возвращающих множество строк, а не только generate_series.
                    Ответить
                    • > общая фишка для функций, возвращающих множество строк
                      Да, так и есть.

                      Currently, functions returning sets can also be called in the select list of a query. For each row that the query generates by itself, the function returning set is invoked, and an output row is generated for each element of the function's result set. Note, however, that this capability is deprecated and might be removed in future releases.

                      А НОК вместо декартового произведения получается из-за того, что одинаковые строки из результата повыкидывало.
                      Ответить
              • Оказывается, оно еще и таймштампы умеет:
                postgres=# select generate_series('28.10.2014', '02.11.2014', interval '1 day') as d;
                           d            
                ------------------------
                 2014-10-28 00:00:00+07
                 2014-10-29 00:00:00+07
                 2014-10-30 00:00:00+07
                 2014-10-31 00:00:00+07
                 2014-11-01 00:00:00+07
                 2014-11-02 00:00:00+07
                Ответить
                • об этом было в их доке

                  бтв
                  http://sqlfiddle.com/#!4/3a8b2/2
                  есть СУБД, где во встроенном языке можно в шаблоны?...
                  Ответить
                  • > об этом было в их доке
                    Я ее невнимательно читал раньше. Вот только сегодня заметил про таймштампы.

                    > http://sqlfiddle.com/#!4/3a8b2/2
                    Красиво. Впрочем в постгресе я тоже так могу ;)

                    > где во встроенном языке можно в шаблоны?
                    Ну если оракл не умеет (а у него же самое продвинутое ООП из всех СУБД, емнип), то скорее всего, что нигде. Кстати, жабья хранимка не может принимать объекты произвольных типов (ну или какого-нибудь супертипа Object)?
                    Ответить
            • у меня там сейчас 1867 записей, и запрос отрабатывает меньше чем за секунду на dev сервере, который мягко говоря слабоват.
              есть еще вариант
              ;WITH
                Pass0 as (select 1 as C union all select 1), --2 rows
                Pass1 as (select 1 as C from Pass0 as A, Pass0 as B),--4 rows
                Pass2 as (select 1 as C from Pass1 as A, Pass1 as B),--16 rows
                Pass3 as (select 1 as C from Pass2 as A, Pass2 as B),--256 rows
                Pass4 as (select 1 as C from Pass3 as A, Pass3 as B),--65536 rows
                x as (select row_number() over(order by C) as Number from Pass4)
              SELECT Number
              FROM x
              WHERE Number <= 10000
              Ответить
              • > меньше чем за секунду
                В постгресе select * from generate_series(1, 10000) отвечает за 1-2мс :) Ну комп, правда, не самый слабый.
                Ответить
          • В tsql есть же циклы. Зачем так извращаться?
            Ответить
    • Может я чего-то не понимаю, но зачем вообще надо иметь таблицу с числами?
      Ответить
      • Чтобы на неё джойнить.
        Допустим есть строка, в неё чего-то упаковано (дни месяца, битовые флаги), джойним пишем substring(i,i+1) и разворачиваем эту упаковку из горизонтальной в вертикальную, которую мы уже можем взять where.
        Ответить
      • Ну самый банальный пример - отчет с разбивкой по дням (дни, по которым нет данных, все равно должны присутствовать в выхлопе).
        Ответить
        • > отчет с разбивкой по дням
          > INSERT INTO `numbers` (`number`) VALUES('9999');
          Наступил 3802 день нашей телестройки...
          Сегодня между ребятами присутствовало со вчерашнего отсутствовало со вчерашнего взор, и только Марина Африкантова стройке, где поссорились на стройке, где поссорились на повышел молодой отец. Напряжение между ребятами присутствовало со вчерашнего в Питер Ильи Григоренко серьёзно пола, Егор Холявин всё ещё несчастлив.
          Ответить
        • кстати, это уже обсуждалось даже на говнокоде
          лучше иметь качественную таблицу dim_dates, с кучей полезных колонок (не только даты, но и дни недели, номер недели, декады, квартала и т.д.), которую заполнить один раз -
          на 10 лет каких-то сраных 3600 строк в ней (для субд это слёзы, когда речь идёт о статистике на миллионы записей за заданный перид отчета),
          чем постоянно на лету генерить какой-то массив
          Ответить
          • Ну да. Тем более такую таблицу один хер приходится делать ради выходных.
            Ответить
            • создавать отдельную таблицу, чтобы там рассчитать день недели? в sql server для этого есть datepart(dw, date_field)
              вообще, там много функций есть для работы с датами http://msdn.microsoft.com/en-us/library/ms186724(v=sql.110).aspx
              Ответить
              • > рассчитать день недели
                Выходные != суббота + воскресенье.
                Ответить
          • Это имеет смысл.

            Тут же просто таблица из одной колонки для чисел.
            Ответить
            • только человек, совершенно лишённый фантазии, не может играть с калькулятором (с)
              в отсутствие generate_series и других инлайн-sql-способов генерации нужной пачки последовательных значений, мастерам майэскуэльного кунг-фу приходится изворачиваться такой говнотаблицей (странно, правда, что 10к записей всего, непорядок)
              хотя, конечно, майскл ни разу в этом месте не оракл, и я бы поостерегся вообще на сторону этой базы переносить в sql то, что можно сделать на, прости господи, php

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

    Добавить комментарий