Comments 30
Возможно, чуть более простое решение бонусного задания:
Case можно и в запрос вставить, но Постгрес с этим, к счастью, сам справляется.
CREATE FUNCTION invert_char(s text) RETURNS text AS $$
SELECT CASE WHEN s ~ '[[:upper:]]' THEN lower(s) ELSE upper(s) END;
$$ LANGUAGE sql;
SELECT string_agg(invert_char(t),'')
FROM regexp_split_to_table(initcap('иВАнОв ИВан иВановиЧ'),'') AS t;
Case можно и в запрос вставить, но Постгрес с этим, к счастью, сам справляется.
+1
Да, здорово!
Выходит, что в данном примере не обязательно выводить порядок для string_agg? Чтобы ничего не сдвинулось без принудительной сортировки.
0
Можно еще для инвертирования регистра использовать функцию translate, тогда решением бонусного задания будет:
select translate(initcap(‘иВАнОв ИВан иВанович’),’АБВГДЕЁЖЗИКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯабвгдеёжзиклмнопрстуфхцчшщьыъэюя’,‘абвгдеёжзиклмнопрстуфхцчшщьыъэюяАБВГДЕЁЖЗИКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ‘) as t;
0
Если ограничиться русским языком, то конечно (:
+1
Почему только русский язык?)
Так это не баг, а фича:)
Меня всегда умиляли подобные подходы к решению
На какие только велосипеды можно не пойти, когда не важно КАК, если главное сейчас и верить что это одноразово
Вот это гениально даже!
Так это не баг, а фича:)
Меня всегда умиляли подобные подходы к решению
На какие только велосипеды можно не пойти, когда не важно КАК, если главное сейчас и верить что это одноразово
Вот это гениально даже!
SELECT reverse(substring(reverse('start long striiing 12345 end') for 10));
SELECT replace(replace(replace('s p a c e', ' ', '<>'), '><', ''), '<>', ' ');
+1
Case можно и в запрос вставить, но Постгрес с этим, к счастью, сам справляется.
Еще немного добавлю
В этой фразе заложен смысл, который не каждый поймет.
О том что в план запроса, вызвавший функцию, будет встроен текст запроса из нее
Как будто мы сами прописали этот CASE в запросе, с меньшими накладными расходами, чем «настоящий» вызов функции
+2
Еще вариант решения бонусного задания
select
array_to_string(array_agg(substring(a from 1 for 1) || upper(substring(a from 2))), ' ')
from
(select unnest(string_to_array(lower('иВАнОв ИВан иВановиЧ'), ' ')) as a) t
+1
1.1 Любой начинающий программист, думаю, когда первый раз столкнулся с явлением разной обработки чисел с плавающей точкой, в зависимости от микросхемы сопроцессора на его материнке, сломал себе моСк, пока не вычитал, или математически не увидел проблему чисел на разных ПК :) Я столкнулся в басике еще, когда начинал писать, дошел до решения сам, просто сравнив простой пример арифметический на двух разных ПК и увидел что числа разные — тогда и вычитал в фидо каком-то что по разному сопроцессоры работают. С тех пор, все условия равенства только нечеткие и обязательное округление, с указанием точных свойств поведения при округлении чисел с плавающей точкой.
В MySQL и SQL Server нет такой х**ни как целый числа в операциях, поэтому SELECT 3/2 выдает как положено 1.5. Если в Postgre это не так — в голову гвоздь забить разрабу, который это придумал.
2.3 NOW() на сколько я знаю, во ВСЕХ языках возвращает не дату, а дату и время. Дату всегда возвращает функция с текстом DATE в названии (в MySQL это CURDATE()). У любой функции в любом языке есть значение инкремента по умолчанию — для CURDATE это 1 день. Поэтому, запрос следующего дня всегда будет SELECT CAST(CURDATE() + 1 AS DATE) без всяких указаний интервалов и прочей чепушины.
Да, вообще вся ваша статья какие-то надуманные грабли и костыли, которых нет в нормальных языках. Просто лень уже стало писать опровержения на каждый ваш пункт — просто пшите на правильных языках и инструментах, и тогда не придется выдумывать себе проблемы на свою… голову.
В MySQL и SQL Server нет такой х**ни как целый числа в операциях, поэтому SELECT 3/2 выдает как положено 1.5. Если в Postgre это не так — в голову гвоздь забить разрабу, который это придумал.
2.3 NOW() на сколько я знаю, во ВСЕХ языках возвращает не дату, а дату и время. Дату всегда возвращает функция с текстом DATE в названии (в MySQL это CURDATE()). У любой функции в любом языке есть значение инкремента по умолчанию — для CURDATE это 1 день. Поэтому, запрос следующего дня всегда будет SELECT CAST(CURDATE() + 1 AS DATE) без всяких указаний интервалов и прочей чепушины.
Да, вообще вся ваша статья какие-то надуманные грабли и костыли, которых нет в нормальных языках. Просто лень уже стало писать опровержения на каждый ваш пункт — просто пшите на правильных языках и инструментах, и тогда не придется выдумывать себе проблемы на свою… голову.
-5
Завтрашний день можно посчитать и как
SELECT current_date + 1
. Другое дело, что в Постгресе это смотрится как кривоватое исключение, сделанное совместимости ради. Интервалы гораздо приятнее, на самом деле.+1
Что значит «писать на правильных языках?»
Приобрести MS SQL из-за “select 3/2” = 1.5?
Приобрести MS SQL из-за “select 3/2” = 1.5?
0
Ну да, ну да, по этому столько крупных компаний использует Postgres.
+1
Какие же еще опровержения вы собрались писать?
1.1 Я как пользователь не причем, что PostrgeSQL так работает. Но показываю это, чтобы осветить нюанс.
2.2 Хочу напомнить, что статья не называется «Делай так, как я показываю», а рассчитана на обучение.
Иначе, я бы писал «показать текущую дату можно так „SELECT current_date“, как вы. Это строка, из которой ничего не выжать (кроме current_time, об этом ниже)
Видимо не все понимают посыл статьи, и готовы цепляться за ерунду.
Я не поленюсь пояснить.
На мой взгляд, чтобы обучаться SQL, надо выполнять запросы и „играться“ с ними.
Мой пример прост для понимания и дает место для фантазии.
Поясню, как бы я его воспринимал, если бы никогда не работал с датами, но желал бы немного разобраться.
Я бы задался вопросом „А что будет, если?“:
И, вдохновившись какими-то результатами, отправлюсь читать MANUAL, т.к. там все темы подробно раскрыты…
Еще мне писали:
Все для того, же… Это просто задача, как в школе о покупке 10 арбузов…
Я сам долго ленился учить регулярки, пока не понял, что все достаточно просто.
1.1 Я как пользователь не причем, что PostrgeSQL так работает. Но показываю это, чтобы осветить нюанс.
2.2 Хочу напомнить, что статья не называется «Делай так, как я показываю», а рассчитана на обучение.
Иначе, я бы писал «показать текущую дату можно так „SELECT current_date“, как вы. Это строка, из которой ничего не выжать (кроме current_time, об этом ниже)
Видимо не все понимают посыл статьи, и готовы цепляться за ерунду.
Я не поленюсь пояснить.
На мой взгляд, чтобы обучаться SQL, надо выполнять запросы и „играться“ с ними.
Мой пример прост для понимания и дает место для фантазии.
SELECT CAST((now()+ INTERVAL '1 DAY') AS DATE)
Поясню, как бы я его воспринимал, если бы никогда не работал с датами, но желал бы немного разобраться.
Я бы задался вопросом „А что будет, если?“:
- заменю DAY на (week, month, year и т.д.)
- заменю +1 на -9000
- заменю DATE на TIME
- уберу CAST
- оставлю только NOW()
и т.д.
И, вдохновившись какими-то результатами, отправлюсь читать MANUAL, т.к. там все темы подробно раскрыты…
Еще мне писали:
"Не представляю, для чего может пригодиться считать количество ЗАГЛАВНЫХ (английских) букв?"
Все для того, же… Это просто задача, как в школе о покупке 10 арбузов…
Я сам долго ленился учить регулярки, пока не понял, что все достаточно просто.
0
Потрясающе!) думаю с этого надо было начать пост! с того как подходить к Вашим примерам.
Спасибо за статью! работаю с PostgreSQL давно, и для опытного DWH само собой ничего нового, но я бы гораздо быстрее освоился в начале карьеры, будь тогда такой материал.
Спасибо за статью! работаю с PostgreSQL давно, и для опытного DWH само собой ничего нового, но я бы гораздо быстрее освоился в начале карьеры, будь тогда такой материал.
Заголовок спойлера
Даже зарегистрироваля ради того, чтоб лайк поставить, но нельзя(
+1
В MySQL и SQL Server нет такой х**ни как целый числа в операциях, поэтому SELECT 3/2 выдает как положено 1.5. Если в Postgre это не так — в голову гвоздь забить разрабу, который это придумал.
Это ложь.
Select 3/2 в MSSqlserver вернет 1.
С чего бы возвращать что-то еще, если оба операнда — целочисленные?
2.3 NOW() на сколько я знаю, во ВСЕХ языках возвращает не дату, а дату и время. Дату всегда возвращает функция с текстом DATE в названии (в MySQL это CURDATE()). У любой функции в любом языке есть значение инкремента по умолчанию — для CURDATE это 1 день. Поэтому, запрос следующего дня всегда будет SELECT CAST(CURDATE() + 1 AS DATE) без всяких указаний интервалов и прочей чепушины.
Не нужно говорить за всех.
Для MSSQLSERVER это будет звучать как:
Select dateadd(day, 1, cast(CURRENTTIMESTAMP AS DATE))
+2
На счет MS SQL — вы правы, просто у меня в настройках стоит коррекция формата SQL, и этот запрос выполняется в моем MS SQL как надо, и возвращает дробь (по дефолту со стандартом мелкомягких — там такой же трабл). Что еще раз говорит о том, что нужно использовать правильный софт и инструменты (или до-настраивать бажные, чтобы не получать такое вот чудо арифметики).
На счет даты — в MSSQL инкрементом дневной даты обладает GETDATE(), так, что её можно использовать без суффиксов (но она плохо оптимизируется, вроде, как).
Вообще, мелокмягкие со своими стандартами SQL, меня достали еще в детстве, в своем косом MSAccess. Я тогда уже их люто невзлюбил за реализацию SQL запросов. И они десятилетяими так и продолжают топтать грабли своих косых разработчиков (впрочем, как и с их IE это у них, наверное какой-то культ там).
На счет даты — в MSSQL инкрементом дневной даты обладает GETDATE(), так, что её можно использовать без суффиксов (но она плохо оптимизируется, вроде, как).
Вообще, мелокмягкие со своими стандартами SQL, меня достали еще в детстве, в своем косом MSAccess. Я тогда уже их люто невзлюбил за реализацию SQL запросов. И они десятилетяими так и продолжают топтать грабли своих косых разработчиков (впрочем, как и с их IE это у них, наверное какой-то культ там).
-2
На счет MS SQL — вы правы, просто у меня в настройках стоит коррекция формата SQL, и этот запрос выполняется в моем MS SQL как надо, и возвращает дробь (по дефолту со стандартом мелкомягких — там такой же трабл). Что еще раз говорит о том, что нужно использовать правильный софт и инструменты (или до-настраивать бажные, чтобы не получать такое вот чудо арифметики).
На счет даты — в MSSQL инкрементом дневной даты обладает GETDATE(), так, что её можно использовать без суффиксов (но она плохо оптимизируется, вроде, как).
Вообще, мелокмягкие со своими стандартами SQL, меня достали еще в детстве, в своем косом MSAccess. Я тогда уже их люто невзлюбил за реализацию SQL запросов. И они десятилетяими так и продолжают топтать грабли своих косых разработчиков (впрочем, как и с их IE это у них, наверное какой-то культ там).
При этом, в том же VB6, который тоже писали ребята из мелкомягких, целочисленное деление, если оно вдруг понадобилось программисту, было реализовано как положено во всех нормальных языках — обратным слэшем \, чтобы явно отличаться от общей операции деления по всем арифметическим правилам. Вот и пойми их там в долине, кто в каком культе состоял и продолжает состоять по сей день.
На счет даты — в MSSQL инкрементом дневной даты обладает GETDATE(), так, что её можно использовать без суффиксов (но она плохо оптимизируется, вроде, как).
Вообще, мелокмягкие со своими стандартами SQL, меня достали еще в детстве, в своем косом MSAccess. Я тогда уже их люто невзлюбил за реализацию SQL запросов. И они десятилетяими так и продолжают топтать грабли своих косых разработчиков (впрочем, как и с их IE это у них, наверное какой-то культ там).
При этом, в том же VB6, который тоже писали ребята из мелкомягких, целочисленное деление, если оно вдруг понадобилось программисту, было реализовано как положено во всех нормальных языках — обратным слэшем \, чтобы явно отличаться от общей операции деления по всем арифметическим правилам. Вот и пойми их там в долине, кто в каком культе состоял и продолжает состоять по сей день.
-1
Нет, ничем подобным GETDATE() — не обладает.
docs.microsoft.com/ru-ru/sql/t-sql/functions/getdate-transact-sql?view=sql-server-2017
Вообще, в MSSQLSERVER — все манипуляции с датой и временем — только через функции даты и времени.
Нет, застарелые олдфаги еще помнят, что datetime можно привести к float, и что-то там делать, например — округлить:
SELECT CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)
Но тем, кто помоложе, гадостям учиться не надо. Не окупается.
docs.microsoft.com/ru-ru/sql/t-sql/functions/getdate-transact-sql?view=sql-server-2017
Вообще, в MSSQLSERVER — все манипуляции с датой и временем — только через функции даты и времени.
Нет, застарелые олдфаги еще помнят, что datetime можно привести к float, и что-то там делать, например — округлить:
SELECT CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)
Но тем, кто помоложе, гадостям учиться не надо. Не окупается.
+1
Спасибо! Пинок и правда есть, но достаточно нейтральный, чтобы не опустить руки :)
Насколько Вам кажется, что нужна теория по устройству СУБД, чтобы писать нормальные запросы?
Насколько Вам кажется, что нужна теория по устройству СУБД, чтобы писать нормальные запросы?
+1
Замечательная статья, пришлось поломать голову над некоторыми вопросами. Бонусные задания решил иначе. Автор, скажите, а когда появится новая публикация в таком же стиле, как и эта? Хочется чего-то вроде и серьёзного, но с другой стороны и веселого.
+1
Спасибо за публикацию. По задаче 2.1 помнил, что есть особенности с NULL. Пришлось перечитать документацию. Пиши ещё.
+1
Немного другая версия задачи 13 от пользователя kirill_petrov на особенность READ COMMITTED
Какие значения окажутся в таблице?
-- Имеется таблица с двумя строками
CREATE TABLE goods (discount) AS
(SELECT 10::INT
UNION ALL
SELECT 15);
-- 1. User_1 выполняет запрос (транзакция остается открыта):
BEGIN;
UPDATE goods
SET discount = discount + 5;
--2. User_2 выполняет запрос:
UPDATE goods
SET discount = discount + 100
WHERE discount = 15
--3. User_1 выполняет
COMMIT;
Какие значения окажутся в таблице?
0
Sign up to leave a comment.
Задачи и решения для бойца PostgreSQL