Поэтому, если у вас стоит задача писать максимально переносимый между СУБД софт, который будет все запросы формировать одинаково понятными для всех СУБД, то либо это будет очень сложным процессом, либо вы получите крайне неэффективные запросы, не использующие хоть какую-то специфику возможностей конкретной базы. То есть любой универсальный запрос на SQL будет одинаково выполняться на всех таких базах, но на всех - не настолько эффективно, насколько можно было бы сделать с учетом специфики.
Предпочтительно избегать необходимости писать кросс-СУБД-код. Лучше уж несколько версий специфичных запросов.
Но ведь никто и не обещал, что PK гарантирует уникальность "во времени", а не "в моменте". А вопросы проектирования БД - тема для отдельного полноценного курса.
Документация говорит, что у SELECT INTO нет преимуществ, так зачем использовать вместо CREATE TABLE AS?
Команда SELECT INTO действует подобно CREATE TABLE AS, но рекомендуется использовать CREATE TABLE AS, так как SELECT INTO не поддерживается в ECPG и PL/pgSQL вследствие того, что они воспринимают предложение INTO по-своему. К тому же, CREATE TABLE AS предоставляет больший набор возможностей, чем SELECT INTO.
В отличие от CREATE TABLE AS, команда SELECT INTO не позволяет задать свойства таблицы, например выбрать метод доступа с помощью указания USING метод или табличное пространство с помощью TABLESPACE табл_пространство. Если это требуется, используйте команду CREATE TABLE AS. Таким образом, для новой таблицы выбирается метод доступа к таблицам по умолчанию.
В этом смысле CREATE TABLE AS выглядит куда логичнее, позволяя определить дополнительные опции для таблицы (филфактор, таблспейс, COMMIT-поведение). А SELECT INTO - это для использования в функциях больше подходит, для помещения результата в переменную.
Запись удалили, но тем не менее это уникальное выражение - присутствует! Например, запрос по нему позволяет убедиться, что запись отсутствует/удалена.
Вот это утверждение не вполне корректно, потому что я могу удалить запись с каким-то значением PK, а затем вставить абсолютно другую, но с тем же значением:
CREATE TABLE _tmp(
x integer
, y integer
, PRIMARY KEY(x)
);
INSERT INTO _tmp(x, y) VALUES(1, 1);
DELETE FROM _tmp WHERE x = 1;
INSERT INTO _tmp(x, y) VALUES(1, 2);
PK гарантирует уникальную идентификацию только для одновременно существующих в таблице записей.
Они фетчатся уже в узле Index Only Scan, если мы считаем агрегаты динамически, а не храним. А если храним - то вычитаем лишь на 1 запись больше указанного лимита.
Таки да, поэтому в реальности для обеспечения стабильности порядка сортировки приходится сортировать по ФИО, коду страны, дополнительным очкам... но если очень хочется "не обидеть", можно использоватьFETCH WITH TIES.
Вполне правильный подход при заведомо малом количестве вариантов - чем-то напоминает "рекурсивный DISTINCT", хотя в общем случае закладываться на такое не выйдет.
Если мы "рулим" обеими сторонами взаимодействия BL <--> DB, то "договориться" можем в любой момент.
Можно ли не сворачивать в json? Конечно, и "отсыпать" TOP-3 за одну дату несколькими записями. Но тогда "агрегировать" в рамках дня придется уже на стороне бизнес-логики, а оно там надо?..
Именно так, поскольку это разные выражения, хоть и с одинаковым результатом вычисления. В документации об этом сказано немного размыто, кстати:
Однако при поиске по индексу индексируемое выражение не вычисляется повторно, так как его результат уже сохранён в индексе. В рассмотренных выше случаях система видит запрос как WHERE столбец_индекса = 'константа'...
Предпочтительно избегать необходимости писать кросс-СУБД-код. Лучше уж несколько версий специфичных запросов.
Но ведь никто и не обещал, что PK гарантирует уникальность "во времени", а не "в моменте". А вопросы проектирования БД - тема для отдельного полноценного курса.
Документация говорит, что у
SELECT INTOнет преимуществ, так зачем использовать вместоCREATE TABLE AS?Убедили, да, слово "хранится" я использовал тут зря (сам ведь писал для нашего коллектора оптимизацию бинарного COPY-формата) - подправил.
В этом смысле
CREATE TABLE ASвыглядит куда логичнее, позволяя определить дополнительные опции для таблицы (филфактор, таблспейс, COMMIT-поведение). АSELECT INTO- это для использования в функциях больше подходит, для помещения результата в переменную.А строкой выше:
И пример с преобразованием timestamp туда-обратно это подтверждает.
Вот это утверждение не вполне корректно, потому что я могу удалить запись с каким-то значением PK, а затем вставить абсолютно другую, но с тем же значением:
PK гарантирует уникальную идентификацию только для одновременно существующих в таблице записей.
Читаем по этой же ссылке:
Точнее, один из покрывающих уникальных индексов.
Включение столбца в PK как раз и накладывает на него NOT NULL:
Разделяю всю боль от разработки бухгалтерского софта . ))
Думаю, начинающему разработчику
SELECT INTOиспользовать придется очень нескоро, поэтому множество вещей в курсе несколько упрощено.А вот тогда уже надо смотреть EXPLAIN ANALYZE.
Как правило, причина одна - нет полностью соответствующего индекса, и запрос уходит в Bitmap Heap Scan или Seq Scan.
нужен индекс
SET enable_seqscan TO off; SET enable_bitmapscan TO off;
Первый вариант - это что-то типа олимпиады по информатике: "кто решил максимум задач - диплом первой степени, на одну меньше - второй".
А второй вариант - это спортивные соревнования "за место" обычно.
В этом смысле есть разные прикладные задачи.
"10 дипломов первой степени, 20 - второй и 30 - третьей" - это как раз про dense_rank.
"Иванов и Петров поделили 1/2 место, а Сидоров с Васечкиным - 3/4" - про WITH TIES.
Они фетчатся уже в узле Index Only Scan, если мы считаем агрегаты динамически, а не храним. А если храним - то вычитаем лишь на 1 запись больше указанного лимита.
Таки да, поэтому в реальности для обеспечения стабильности порядка сортировки приходится сортировать по ФИО, коду страны, дополнительным очкам... но если очень хочется "не обидеть", можно использовать
FETCH WITH TIES.Вполне правильный подход при заведомо малом количестве вариантов - чем-то напоминает "рекурсивный DISTINCT", хотя в общем случае закладываться на такое не выйдет.
Если мы "рулим" обеими сторонами взаимодействия
BL <--> DB, то "договориться" можем в любой момент.Можно ли не сворачивать в json? Конечно, и "отсыпать" TOP-3 за одну дату несколькими записями. Но тогда "агрегировать" в рамках дня придется уже на стороне бизнес-логики, а оно там надо?..
Именно так, поскольку это разные выражения, хоть и с одинаковым результатом вычисления. В документации об этом сказано немного размыто, кстати:
А что мешает с пользой применять индекс по этому выражению?