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

    −41

    1. 1
    (CASE WHEN "order".payment_type = 1 AND payed = 0 THEN 0 ELSE 1 END) = 1

    Одно из индусских условий в WHERE. Выражение вполне можно сократить до такого:

    ("order".payment_type <> 1 OR payed > 0)
    или такого:
    NOT ("order".payment_type = 1 AND payed = 0)

    Запостил: jbot, 31 Мая 2016

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

    • Гибкий код на случай, если при выполнении/невыполнении условия должно подставляться не фиксированное 0 и 1, а значение некоторого поля.
      Сие не ГК, сие эталон продуманности, умения решать задачи шире поставленных. Гарбер рыдал бы слезами восторга и умиления.
      Ответить
      • Ма́рк Рафаи́лович Га́рбер — (2 января 1958, Москва) — российский предприниматель, писатель, миллиардер?
        Ответить
        • Martin Gruber, мог бы и догадаться из приличия.
          Ответить
          • гуглянул - даже гугля похоже не знает. не томи, гость, открой секрет.
            Ответить
            • Гугля знает

              Неплохой букварь, правда

              ПОНИМАНИЕ SQL" о
              Ответить
              • Стоит прочтения?
                Ответить
                • Ну если ты дуб в sql, или если есть день вреиени то стоит
                  Ответить
                  • не, хочется научиться писать высокоэффективные запросы
                    Ответить
                    • Я бы читал рефакторинг sql, но в идеале нужно читать про конкретную субд. Все таки эффективность запросов это не только нормализация и индексы, это еще работа с оптимтзатором, а он разный на разных бд, впрочем как и индексы могут отличаться
                      Ответить
                      • Для MSSQL есть нормальная книга по написанию запросов. не в курсе?
                        Ответить
                        • Я читал древнюю, еще про 2005. Она была родная, от microsoft.

                          Вот вроде есть

                          Choose the right transaction isolation level and concurrency model

                          Take control over query plan caching and reuse

                          https://www.microsoftpressstore.com/store/microsoft-sql-server-2012-internals-9780735658561
                          Ответить
                          • спс, посмотрю, что пишут
                            Ответить
                          • Choose the right transaction isolation level and concurrency model
                            Take control over query plan caching and reuse
                            Rule the world
                            Ответить
                            • смех смехом, а 99% "программистов интерпрайза" не назовут тебе с ходу уровни изоляции транзакций. И что такое кластерный индекс не знают. И что такое B-tree index. Короче, книги про БД реально надо читать.
                              Ответить
                              • > уровни изоляции транзакций
                                Дык там у каждой субд ещё и своё понимание этих уровней...

                                Тот же слоник, к примеру, вообще не умеет в read uncommitted. А на repeatable read, емнип, он даёт намного более строгую гарантию, чем надо по стандарту - снепшот на момент первого запроса в транзакции.
                                Ответить
                                • стоп стоп стоп) На каждом уровне он обязан гарантировать отсутствие определенных phenomena (как по-русски? явления?).

                                  Так вот на read uncommited он обязан не гарантировать ничего. Что он и делает. А что по-факту uncommited read не виден никогда -- так это не его проблема)
                                  Ответить
                                  • Ну вот он гарантирует больше, чем обязан. Это не плохо, просто люди к этому привыкают и считают нормой. А потом на другой СУБД, на которой эти феномены всё-таки проявляются, налетатают на грабли.
                                    Ответить
                                    • А потому что учить нужно СНАЧАЛА интерфейс, а только потом особенности реализации
                                      Интерфейс называется ANSI SQL, там есть описание всех четырех уровней

                                      Вот кстати в этом плане Gruber хорош: он имплементейшен-агностик довольно
                                      Ответить
                                      • > ANSI SQL
                                        На ANSI SQL ты только лабу напишешь, и то не факт...
                                        Ответить
                                        • на SQL:2011 вполне себе напишешь что-то работающее:)

                                          Я не спорю что в реальных проектах есть код (ну процентов 20) который надо писать с учетом конкретной БД, просто знать стандарт все равно нужно.

                                          Например ты можешь оптимизироваться под конкретный компилятор или проц, но это не избавляет тебя от знания ANSI C или JMM, правда?
                                          Ответить
                                          • > SQL:2011
                                            Вот только его никто не поддерживает, лол.

                                            > SQL/XML
                                            А где йосон иль еще какой стандарт?

                                            > SQL/PSM
                                            На самом деле круто. Многое есть. Стандартную библиотеку бы еще стандартизировали... Но даже кресты в это не могут, по капле из моря(

                                            > Дык там у каждой субд ещё и своё понимание этих уровней...
                                            snapshot isolation level + sp_getAppLock. Остальное не нужно, сирисли.
                                            Ответить
                              • > И что такое B-tree index
                                А есть хоть одна реляционная бд, где можно выбрать тип индекса? Ну кроме кластерный\не кластерный. По моему нет, так что не особо полезно. И вообще даже нет возможности выбрать индекс case sansative индекс или нет. Не то чтоб какие-нибудь хеш индексы или трии индексы
                                Ответить
                                • > где можно выбрать тип индекса
                                  Няшный постгрес.
                                  Ответить
                                  • я склоняюсь к тому, что бостгрес вообще самый няшный из всех.

                                    Но в слову в постгресе больше всего тонких моментов аля уб
                                    Ответить
                                    • ub там не заметил
                                      много интересных фишечек, опережающих pl/sql

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

                                      dblink постгресовый удобен как говно, mat view как говно, даже партиционирование и то ведет себя при инсертах как говно и ломает ожидания хибернейту

                                      нет ничего идеального
                                      Ответить
                                      • > ub там не заметил
                                        создание concurently индекса - сплошной уб
                                        Ответить
                                • в оракле можно заебаться и сделать индексирование по своим правилам, например, оконной функции
                                  https://docs.oracle.com/cd/B19306_01/server.102/b14200/ap_examples001.htm#i690409

                                  а уж про case insensitive - индексируй lower(foo), и селекти lower(foo), чтобы оптимизатор индекс цеплял, это будет годно для любой субд с поддержкой function-based indexes, вместо того, чтобы запоминать какие-то (нестандартные?) параметры создания регистронезависимого индекса в конкретной субд
                                  Ответить
                                  • ну в некоторых субд есть вычислимые на лету колонки. Вот на этом можно строить индекс
                                    Ответить
                                    • кстати, в постгресе их нет
                                      кстати, внутри оракла function-based сам по себе создает виртуальную колонку к таблице, она просто заодно ещё и скрытая
                                      Ответить
                                      • слушай, вот ты говоришь оракл как будто это что-то хорошее. это так? а покупать его обязательно или можно юзать бесплатно как какой-нибудь скллайт?
                                        Ответить
                                        • я не говорю что оракл это лучше всех

                                          все новые проекты последние года полтора мы зачинаем строго на постгресе, по многим причинам

                                          я просто указываю на досадные и (внешне) несложные вещи, недоделанные в постгресе, с надеждой, что они когда-либо исправятся

                                          в оракле тоже совсем не все так сладко, но тот факт, что за десяток проектов я в горячке постгрес не удалил, заменив его ораклом, а методично преодолевались проблемы худо-бедно, тоже о чем-то да говорит

                                          оракл версии стандарт и выше покупать обязательно, если ты его применяешь в продакшен целях

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

                                          также есть экспресс едишен, он лимитирован, но официально бесплатен, матрицу сравнений редакций можешь посмотреть на сайте
                                          Ответить
                                          • сегодня боремся с очередным постгресоговном

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

                                            оказалось везде минное поле

                                            bytea хоть и хранится там где надо (TOAST раскладывается по партициям наравне с материнской таблицей), но протокол его походу искейпит вдоль и поперек, и вместо 100МБ файла гоняется трафик в 2-3 раза бОльший, да и ограничение имеет в 1GB (как бы, ага)

                                            oid (это типа постгресный настоящий LOB) хранится в пизде, одна системная таблица на всю БД, никакого партиционирования уже тут нет, нельзя тут хранить сотни тыщ файлов, больших и малых

                                            и даже хер бы с ними с недостатками bytea, но ведь драйвер его внатуре гоняет через буферы сессии, и на инсерте файла чуть большем, чем 128M постгрес киляет сессию по OOM, невзирая, например, на настройки shared_memory = 1GB

                                            вот такая вот enterprise-ready СУБД
                                            Ответить
                                            • > вот такая вот enterprise-ready СУБД

                                              То ли дело MySQL.
                                              Ответить
                                            • Переходи на Mnesia, у нас есть дедлоки.
                                              Ответить
                                              • КАК?
                                                Ответить
                                                • Прошлая версия OTP, которую мы использовали, этим багом славилась -- при создании многих таблиц одновременно одна-две изредка повисали.
                                                  Ответить
                                      • кстати, а ты какие изолейшен левелы юзаешь? мне кажется снапшот-бэйст хватит всем
                                        Ответить
                                        • нет ничего лучше дефолтного левела - read committed

                                          использование более строгих должно сопровождаться уверенностью, что это реально необходимость, а не подпирание костылями хуево спроектированной схемы или хуево продуманной логики
                                          Ответить
                                          • Риад комитет - типичное тормозное дедлочное говно. При снапшоте никаких пауз или ожиданий
                                            Ответить
                                            • дедлок - тоже признак хуевой схемы и хуевой логики

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

                                              ну так вот, хорошо работает сериалайзед на этих таблицах в охулиард? или всё же проще строки лочить? что сильнее тормозит?
                                              Ответить
                                              • Снапшот - это противоположность сериалайзед. Вообще все одновременно идёт.
                                                Ответить
                                                • в стандарте описаны 4 уровня изоляции, и в оракле и в постгресе они используются в документации, я не знаю что такое уровень снапшот, кроме того, что это снимок системы, а снимок системы, видимо - сериалайзед, ты фиксируешь состояние субд на момент начала транзакции, ты делаешь вид, что нет никого кроме тебя, и тебя не попускает, пока не сделаешь коммит

                                                  > в стандарте описаны 4 уровня изоляции
                                                  воспользуйся ими и ты
                                                  Ответить
                                                  • > снапшот
                                                    Это что-то из M$$QL вроде.

                                                    З.Ы. Кстати, у постгреса repeatable read это и есть снимок на момент первого запроса в транзакции...
                                                    Ответить
                                                    • снимок таблицы и снимок всей схемы - все же есть нюанс между repeatable read и serialized
                                                      Ответить
                                                  • https://msdn.microsoft.com/ru-ru/library/ms173763.aspx

                                                    READ UNCOMMITTED
                                                    | READ COMMITTED
                                                    | REPEATABLE READ
                                                    | SNAPSHOT
                                                    | SERIALIZABLE

                                                    сериалайзед это когда все последовательно. упоротый лок на все, если юзаешь общие таблицы между запросами

                                                    снапшот - снимок закомиченного. спокойно все параллельно читается и апдейтится. если параллельно апдейтить одну строку с другим запросом, то запросу с меньшим приоритетом не везет и он отваливается и надо повторять, если это еще актуально
                                                    Ответить
                                                    • звучит плохо
                                                      мне лень доки читать, объясни на пальцах

                                                      у меня есть таблица А и таблица Б, в которой внешний ключ на А

                                                      транзакция 1 вставляет в таблицу А строку со значением id = 10, его еще нет, ничего не нарушается, вставляет в таблицу Б две строки, которые ссылаются на A.id=10

                                                      параллельно с этим транзакция 2 тоже вставляет в таблицу А строку с тем же значением id, и вставляет в таблицу Б три строки, ссылающиеся на А.id=10

                                                      что произойдет после коммита обеих транзакций?
                                                      Ответить
                                                      • Ну если А.id первичный уникальный ключ, то одной из транзакций не повезет, по моему это очевидно, тк она вставит дублирующийся ключ. Другая закомитится как и положено
                                                        Ответить
                                                        • в смысле дублирующийся?
                                                          она же не видит изменений первой транзакции, ты же сам говоришь
                                                          Ответить
                                                          • не видит до комита и если тут окажется, что писал в одни и теже строки, то откатится при комите. На самом деле откатится уже при изменении скорее всего, если оно было направленно на одни и теже данные. А так то селектами не видит чужих данных
                                                            Ответить
                                        • ебашь сериалайзед @ оборачивай все апдейты в циклы
                                          Ответить
                                          • Так все апдейты и нужно в циклы оборачивать. А ты как думал?
                                            Ответить
                                            • > Так все апдейты и нужно в циклы оборачивать
                                              На read committed - нинужно.
                                              Ответить
                                              • Да ладно. Ты так говоришь как будто на риад комитет deadlock viсtim не может быть
                                                Ответить
                                                • Как надо выебнуться, что бы на read committed получить дедлок?

                                                  Пример кода в студию.
                                                  Ответить
                                                  • sp_getAppLock заюзай, захватывая локи в разном порядке)))
                                                    Ответить
                                                    • > захватывая локи
                                                      Ну бля, хуй тоже можно сломать...
                                                      Ответить
                                                  • и вообще как можно жить, когда каждый следущий стэйтмент в транзакции тебе может вернуть данные, не те, что были на начало транзакции. Это какая-то дрянь. Так что без снапшота жизни нет
                                                    Ответить
                                                    • а зачем ты лезешь в те же таблицы в те же строки, с которыми уже только что поработал? на что ты рассчитываешь?
                                                      Ответить
                                                      • ну это не я лезу, а в системе много клиентов. я что им буду отказывать в обслуживании, если попросят поменять одну строку одновременно?
                                                        Ответить
                                                        • нет, это означает, что кто первый встал, тот первый и обновил
                                                          второй запрос на изменение этой строки её перезапишет сразу, как только субд снимет блокировку этой строки

                                                          представь себе личный кабинет и свое ФИО в нем, ты зашел с двух разных устройств, нажимаешь редактировать, и почти одновременно посылаешь на сервер "обнови мне их на вот это новое значение" - какое останется в итоге? которое придет вторым

                                                          и серверу не важно, что второе пришло на миллисекунду позже или на 6 месяцев позже первого

                                                          но это совсем не о том, о чем я выше писал
                                                          > следущий стэйтмент в транзакции тебе может вернуть данные, не те, что были на начало транзакции
                                                          такое может быть, если ты сначала поселектил 10 строк в таблице А по конкретному условию, на основе них поселектил 20 строк в таблице Б, это всё обработал, а потом в той же транзакции за каким то хером снова полез селектить из таблицы А с тем же условием и получил 11 строк - вот и вопрос, нахера ты лезешь 2 раза за теми же строками
                                                          Ответить
                                                          • > такое может быть, если ты сначала поселектил 10 строк
                                                            Так вот из-за этого можно сломать инвариант, например когда
                                                            if exist (select ...) then insert ...
                                                            Первый селект покажет один результат, а второй инсерт уже будет инсертить в измененную в другой транзакции таблицу с уже измененным условием if. Состояние гонки. И может даже эксепшен за дубликаты первичного ключа выкинуть.

                                                            А merge в sql server поломан и не помогает)))
                                                            Ответить
                                                            • > if exist (select ...) then insert ...
                                                              да, только if not exists
                                                              в этом случае надо ставить лок на таблицу в нужном режиме (чтобы её могли, например, читать, но не могли менять), делать свои дела как можно быстрее и снимать лок

                                                              а если ты все же имел в виду if exists, то есть более мягкий лок - select for update
                                                              Ответить
                                                              • select for update хоть он и мягкий, но до конца транзакции. Раньше не снять... А в некоторых субд и локов то нет, типа фаерберда... Ну кроме селект вис лок или селект вис лок фор апдейт
                                                                Ответить
                                                                • > но до конца транзакции. Раньше не снять.
                                                                  Транзакции должны быть резкими и острыми как бритва. Раз у тебя транзакции часами висят - ну понятно, откуда дедлоки и прочее говно.
                                                                  Ответить
                                                                  • И такое бывает. Не я один пишу эту многолетнюю систему. Ей уже лет 10. Там все можно найти. Код довольно читабильный, но скоростью и оригинальностью решений не отличается
                                                                    Ответить
                                                • можно и хуй сломать
                                                  только цикл тут причем?
                                                  чинить надо приложение, а не делать несколько попыток
                                                  Ответить
                                                  • Сломать хуй нельзя. Только порвать. Не путай меня. Там нет костей. Там пневмосистема с клапаном и кровянным резервуаром
                                                    Ответить
                                                    • > Сломать хуй нельзя.

                                                      1. Бывает травма, которую называют переломом пещеристого тела. Возникает, когда к эрегированному члену прикладывают нагрузку в направлении, перпендикулярном его оси.

                                                      Возле основания полового члена в пещеристом теле разрываются перегородки, и кровь растекается там, где её не ждут.

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

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

                                                      Да, бывает перелом бакулюма.
                                                      Ответить
      • Отчасти согласен, может в более общей ситуации это было бы оправдано. Но в данной ситуации этот кусок запроса предназначен только для проверки условия, не более, так что здесь CASE лишний. К тому же доработать условие в будущем при необходимости будет несложно, нет смысла все усложнять.
        Ответить
      • сомневаюсь. тут очевидно кто-то облажался с булевой алгеброй.

        потому что сравнение выражения с полем, с точки зрения SQL, есть еще большее говно.
        Ответить
    • А ничего, что оба предложенных варианта делают не то же самое, что код. Или там not null?
      Ответить

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