PostgreSQL SUM CASE выражение с ТОГДА 1, ТО 0, ЛИБО 0

Здесь кое-что происходит ...

Объявление [...] создает фактический массив вместо среза, поэтому удаление косвенности удаляется. То, что объявляется здесь, представляет собой массив типов interface{} ... так что вы можете задаться вопросом, почему странная нотация карты?

Переменные StateXXX - это просто константы, объявленные выше, поэтому они являются ints ... так что объявление действительно имеет форму index: value.

Ниже представлен менее запутанный пример того, что использование массива ints:

var i = [...]int{4: 2, 2: 7}

Это будет выделение массива содержащий:

[0, 0, 7, 0, 2]

... обратите внимание, что индекс 2 имеет 7, индекс 4 имеет 2. Не является общепринятым способом объявления массива, но он действителен. Go.

вернемся к первоначальному объявлению, просто возьмите пример, который я привел выше, а вместо int сделаем массив типа interface{}:

var i = [...]interface{}{4: 2, 2: 7}

И вы получите аналогичный массив, но с nil вместо нулей.

Подойдя ближе к исходному коду, константы StateXXX - это просто ints, только не литералы, как в моем примере.

Итак, в чем смысл всего этого? Почему все обфускации?

Это взлом производительности. Функция c.curState.Store() принимает аргумент типа interface{}. Если вы должны передать ему int, скомпилированный код должен был бы перепутаться с преобразованием типа для каждого вызова. Более ясная (хотя, очевидно, непрактичная) иллюстрация этого может быть:

var val interface{}

for i := 0; i < 1000000; i++ {
    // the types are different, compiler has to fumble int vs. interface{}
    val = i
    // do something with val
}

Каждый раз, когда вы делаете val = i, должно произойти преобразование между int и interface{}. Выделенный вами код избегает этого, создавая статическую таблицу поиска, где все значения уже интерфейса типа.

Поэтому это:

c.curState.Store(connStateInterface[state])

более эффективен, чем это:

c.curState.Store(state)

Так как state, в этом случае, необходимо пройти преобразование int -> interface{}. В оптимизированном коде state представляет собой просто индекс, который ищет значение в массиве, результат которого дает вам interface{} ... поэтому избежать преобразования типа int -> interface{}.

Я не знаком с этим кодом, но я бы предположил, что он находится на критическом пути, и наносекунды или любые сбережения сбережения, вероятно, имеют значение.

0
задан a_horse_with_no_name 20 January 2019 в 08:49
поделиться

2 ответа

CASE возвращает значение первого (сверху вниз) выражения THEN, которое имеет выражение WHEN, которое оценивается как true (и ELSE, если ничего не найдено). Поскольку ваше первое WHEN также верно в случаях, когда второе верно, выбирается первое, а не второе. Всегда ставьте более узкий WHEN перед менее узкими в CASE.

CASE
    WHEN (type_txt = 'ACCOUNT' AND status = 'ACTIVE' AND code = 483 AND open_date < CURRENT_DATE) THEN 0
    WHEN (type_txt = 'ACCOUNT' AND status = 'ACTIVE' THEN 1
    ELSE 0
END
0
ответ дан sticky bit 20 January 2019 в 08:49
поделиться

Поместите дополнительное условие в тот же случай:

sum(
    CASE
        WHEN 
            type_txt = 'ACCOUNT'::text 
            AND status = 'ACTIVE' 
            AND NOT (code = 483 AND open_date < CURRENT_DATE) 
        THEN 1
        ELSE 0
    END) AS accounts_actv
0
ответ дан klin 20 January 2019 в 08:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: