Как создать столбец в postgres из значений и выборок на основе других столбцов?
Я хочу создать новое поле (или два) в моей таблице, которое является конкатенацией других полей, что кажется относительно простым. Но что такое case
синтаксис или if/when
синтаксис, который я бы использовал для создания следующих полей (GPA_TXT
и newfield
)?
логика такова: каждый GPA должен быть #.#
, каждое новое поле должно быть:
name & "-" & GPA_TXT & (
case where GPA_TXT > 3.3
set newfield = newfield & 'GradeA',
case where GPA_TXT >2.7 and GPA_TXT < 3.3
set newfield = newfield & "GradeB",
etc...
)
например:
name major GPA(num) GPA_TXT [newfield]
Bob sci 2 02.0 Bob-sci-GradeC-02.0
Jane chem 3.1 03.1 Jane-chem-GradeB-03.1
Charlie phys 3.7 03.7 Charlie-phys-GradeA-03.7
Garfield food 0 00.0 Garfield-food-GradeF-00.0
Итак, я думаю, у меня есть два вопроса здесь:
- как создайте поле GPA TXT.
- как написать оператор case для вычисления поля в соответствии со значениями в других полях.
если кто-нибудь может связать меня с ресурсом с примерами или объяснить, я был бы очень признателен! Я просматриваю документацию, но не получаю ничего без примеров.
3 ответов
важное примечание: Я бы создал посмотреть на основе текущей таблицы и избежать добавления новых столбцов, как они будут денормализация схемы. Подробнее здесь.
кроме того, я буду использовать строчные имена для всех идентификаторов, чтобы избежать qouting.
- в форме
GPA_TXT
поле вы можете использоватьto_char()
функция:to_char(gpa, 'FM09.0')
(theFM
будет избегать пространства перед результирующим string); -
для второго поля я бы использовал
GPA
, а неGPA_TXT
для числового сравнения. Вы можете проверитьCASE
конструкции документы, но блок может быть следующим:CASE WHEN gpa >= 3.3 THEN 'A' WHEN gpa > 2.7 AND gpa < 3.3 THEN 'B' WHEN gpa > 0 THEN 'C' ELSE 'F' END
Извините, я не знаю, как назначаются оценки за GPA, пожалуйста, отрегулируйте соответственно.
результирующий запрос для представления может быть (также на среда SQL Скрипка):
SELECT name,major,gpa,
to_char(gpa, 'FM09.0') AS gpa_txt,
name||'-'||major||'-Grade'||
CASE WHEN gpa >= 3.3 THEN 'A'
WHEN gpa > 2.7 AND gpa < 3.3 THEN 'B'
WHEN gpa > 0 THEN 'C'
ELSE 'F' END || '-' || to_char(gpa, 'FM09.0') AS adesc
FROM atab;
чтобы построить представление, просто добавьте CREATE VIEW aview AS
перед этим запросом.
редактировать
если вы все еще идете для добавления столбцов, следующее должно сделать трюк:
ALTER TABLE atab ADD gpa_txt text, ADD adesc text;
UPDATE atab SET
gpa_txt = to_char(gpa, 'FM09.0'),
adesc = name||'-'||major||'-Grade'||
CASE WHEN gpa >= 3.3 THEN 'A'
WHEN gpa > 2.7 AND gpa < 3.3 THEN 'B'
WHEN gpa > 0 THEN 'C'
ELSE 'F' END || '-' || to_char(gpa, 'FM09.0');
Я рекомендую" сгенерированный " столбец, а не хранить данные избыточно. Это займет меньше места на диске, что, скорее всего, сделает его быстрее, чем сохранение сгенерированного значения, и, безусловно, будет менее подвержено случайному выпадению из синхронизации с базовыми данными. Предполагая, что вам нравится формат, предоставленный @vyegorov, вы можете создать такую функцию, используя тип записи вашей таблицы (который соответствует имени таблицы) в качестве входных данных:
CREATE FUNCTION adesc(rec atab)
RETURNS text
IMMUTABLE
LANGUAGE SQL
AS $$
SELECT to_char(.gpa, 'FM09.0') AS gpa_txt,
.name||'-'||.major||'-Grade'||
CASE WHEN .gpa >= 3.3 THEN 'A'
WHEN .gpa > 2.7 AND .gpa < 3.3 THEN 'B'
WHEN .gpa > 0 THEN 'C'
ELSE 'F' END || '-' || to_char(.gpa, 'FM09.0') AS adesc;
$$;
вам нужно будет ссылка на это с помощью квалификатора отношения (имя таблицы или псевдоним). Если такая ссылка не разрешена путем поиска фактического столбца, PostgreSQL будет искать функцию, принимающую тип записи таблицы в качестве единственного параметра. Таким образом, Вы сможете сделать что-то вроде этого:
SELECT name, major, gpa, atab.adesc
FROM atab;
такой "сгенерированный столбец" можно использовать в индексах для быстрого поиска, если это то, что вам нужно, с чем-то вроде adesc(atab).*
.
вот запрос, который возвращает значения из таблицы с 3 столбцами:
select *
, to_char(gpa, '09.9') as gpa_text
, name || '-' || major || '-Grade' ||
case when gpa between 3.5 and 4.0 then 'A'
when gpa between 2.5 and 3.4 then 'B'
when gpa between 1.5 and 2.4 then 'C'
when gpa between 0.5 and 1.4 then 'D'
else 'F' end
|| '-' || ltrim(to_char(gpa, '09.9')) as newfield
from students
это рабочий код, вот новое поле для Боба, "Боб-sci-GradeC-02.0"
Я настоятельно рекомендую, чтобы у вас не было текстового столбца в базе данных для хранения дубликата числового значения. Я не совсем уверен, зачем мне нужен ltrim, кажется странным, что форматированная строка будет иметь ведущий пробел.