LINUX.ORG.RU

Как вернуть длинный ряд после join?

 ,


0

2

Hello, LOR

Пишу веб сервис на typescript. Прислушавшись к громкому меньшинству, принял решение не испоьзовать ORM, а писать прям SQL-запросы (строковыми литералами).

Сперва все пошло более-менее ровно, пока не появился JOIN. Та самая хваленая оптимизация, делающая один запрос там, где какая-нибудь ORM делает N+1

Условно, есть таблица «товары» и таблица «свойства_товара». Наивным способом сначала загружаем список товаров, затем в цикле SELECT-им свойства каждого по uid.

Но мы же крутые. Обладая всей мощью SQL, делаем «товары LEFT JOIN свойства_товара». И получаем.. Херню мы получаем! Длинный ряд столбцов. С повторяющимися именами (в этих таблицах есть одноименные столбцы). А с учетом того, что заботливый драйвер postgres превращает ряды в словари, одинаковые имена просто схлопываются

Погуглил что предлагает коллективный надмозг. Надмозг предлагает жесть. Разделять столбцы разделителями и потом програмно собирать эту змею в объекты:

---- foo, bar из первой таблицы. baz, bang из второй
SELECT foo, bar, '|', baz, bang

Подскажите, есть ли более лучший способ? Postgresql декларируется как фичастый и объектный. Должен же быть способ получше? Как вернуть из базы ответ в более структурированном виде? Может есть способ при селекте как-то скомбинировать поля и вернуть одним полем. Или еще как-то?



Последнее исправление: pornandme (всего исправлений: 1)

Ответ на: комментарий от deep-purple

Но вьюшка-то хранится на стороне базы и по ней тоже можно делать выборки. И делается это только один раз, и не надо каждый раз трахаться с формированием наркоманского запроса.
Но это я больше для топикстартера расписываю.

mord0d ★★★★★
()
Ответ на: комментарий от mord0d

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

а еще у нас както один деятель нагавнякал на питоне плагин, или как его, для постгри, так пацаны потом два месяца искали почему такие странные выборки - в бекенде то все ровно было.

deep-purple ★★★★★
()
Ответ на: комментарий от level1

«Отношение», «Кортеж», «Атрибут» - это таблица, строка, столбец, соответственно.

Шизофазия на марше. Ты чушь порешь.

no-such-file ★★★★★
()
Ответ на: комментарий от deep-purple

пока чтото не поменялось

Проектирование для слабаков?

а еще у нас както один деятель нагавнякал на питоне плагин, или как его, для постгри, так пацаны потом два месяца искали почему такие странные выборки - в бекенде то все ровно было.

Тестирование, видимо, тоже. (%

mord0d ★★★★★
()
Ответ на: комментарий от Toxo2

Может быть потому что SQL это про СУРБД? В реляционной модели не бывает деревьев. Первое правило Кодда.

Нет таких ограничений в реляцонной модели, все это ограничения реализаций.

Hint: отношение – это тоже значение.

anonymous
()
Ответ на: комментарий от no-such-file

Шизофазия на марше. Ты чушь порешь.

Может тебе начать с теории прежде, чем такое человеку заявлять?

anonymous
()

Подскажите, есть ли более лучший способ? Postgresql декларируется как фичастый и объектный. Должен же быть способ получше? Как вернуть из базы ответ в более структурированном виде? Может есть способ при селекте как-то скомбинировать поля и вернуть одним полем. Или еще как-то?

Што? Именуй поля через AS и используй GROUP BY и агрегирующие функции. Можешь дополнительно использовать подзапросы - они разворачивается в те же самые джойны, но в некоторых случаях избавляют от лишней писанины и выглядят более читабельно:

SELECT
   name,
   foo,
   bar,
   (SELECT array_agg(value) FROM properties WHERE properties.name = items.name) AS properties
FROM items

VIEW использовать не советую, потому что он не даст потом менять схему нижележащих таблиц, придётся на каждое изменение схемы его пересоздавать. Запросы должны создаваться на клиенте, а не храниться на сервере в виде view.

slovazap ★★★★★
()
Последнее исправление: slovazap (всего исправлений: 1)

Хотел было написать, что нашел решение в виде наследования таблиц. Но как оказалось, наследование в постгре недоделанное. Много чего не работает..

pornandme
() автор топика
Ответ на: комментарий от mord0d

Проектирование

С реалиями того, как и сколько раз чешут менеджеры пятку — лучше спроектировать без битов. Или с битами, но спасёт только опыт.

Тестирование

Да, в те времена о тестировании не задумывались.

deep-purple ★★★★★
()
Ответ на: комментарий от pornandme

Точно бывают?

Пардон. Я тут в Сети покопался на эту тему. Оказывается у меня устаревшая информация. Оно, как Феникс, опять живое )

Если будет любопытно - вот здесь: https://www.pickmultivalue.com/ целые фильмы совсем новые, 2020 год.

Странно, что в фильме про файловую систему не услышал (или прослушал) главную её фишку - поля корреляции. В терминах реляционной БД это было бы что-то вроде «вычислимого поля», наверное. (т.е. когда значение «поля» таблицы вычисляется на лету при обращении к нему - по данным других таблиц, например).

Забавно выглядит, что все персонажи на фото и видео где-то в районе 60+ )

И, кстати, отечественный вариант этой же парадигмы - Cronos. Тот же MultiValue только «немного в профиль». Но страшно обижаются, когда им говорят, что они на кого-то похожи. )

Toxo2 ★★★
()
Последнее исправление: Toxo2 (всего исправлений: 2)
Ответ на: комментарий от Toxo2

Так там, насколько я понял, язык запросов а ля SQL: LIST PEOPLE LAST_NAME FIRST_NAME EMAIL_ADDRESSES WITH LAST_NAME LIKE «Van…». То есть сути не меняет. Все равно в коде придется писать строки на инглише со вкраплениями переменных. Я надеялся на что-нибудь с API. Или на общением через структуры данных, как в монге. В общем на то, что можно генерить средствами ЯП, а не склейкой строк

ЗЫ Имя создателя улетное https://en.wikipedia.org/wiki/MultiValue#History

pornandme
() автор топика
Ответ на: комментарий от Toxo2

Я не про СУБД и как хранить, а про формат dto. Сейчас любой комбинаторный бумс летит сотнями копий, тогда как можно бы древовизировать его, зная как это делать из самого факта джойна, и на клиент слать только уникальные части выборки. А он уж решит, развернуть это в таблицу или оставить так, что чаще всего и нужно.

anonymous
()

Херню мы получаем! Длинный ряд столбцов. С повторяющимися именами (в этих таблицах есть одноименные столбцы).

1.Раздай алиасы.
2.Зачем ты всё делаешь руками? Сделай какой-нибудь конструктор запросов что-ли. ОРМы, конечно, бывают тем еще говном, но об стенку-то головой биться зачем.
3.Структуру в студию. У тебя свойства не key-value? Решил, уж раз ссать против ветра, так по полной? Или считаешь eav дикой ересью?
4.Если есть одинаковые столбцы, то ты должен получить неоднозначность и запрос свалится. Ну, если там не select * ...

А с учетом того, что заботливый драйвер postgres превращает ряды в словари, одинаковые имена просто схлопываются

Кури документацию драйвера на этот счёт. Должна быть опция, чтобы он добавлял имя таблицы хотя бы или засовывал записи с разных таблиц в разные объекты, ну и в крайнем случае - в один массив и пробовать тянуть метаинформацию о полях в запросе. Если не накуришь, делай алиасы и конструктор.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 3)
Ответ на: комментарий от crutch_master

Сделай какой-нибудь конструктор запросов что-ли

С конструктором, без ORM все равно лапша будет. Написать sql руками не проблема. Проблема что типы не выводятся, если изначально всё-всё не описывать в терминах сущностей ORM-а и не селектить исключительно апишечкой ORM-а

Или считаешь eav дикой ересью?

Просто не знал что так делают. На первый взгляд какая-то хрень, да, но потенциал чувствуется

Должна быть опция, чтобы он добавлял имя таблицы хотя бы или засовывал записи с разных таблиц в разные объекты

В postgresиnode-postgres нету. psql тоже игнорит точечную нотацию. Подозреваю, что в протоколе не предусмотрено

pornandme
() автор топика
Ответ на: комментарий от pornandme

С конструктором, без ORM все равно лапша будет.

Сделай так, чтобы не было. Конструктор не только про то, что не писать sql руками, а про метаинформацию - какие таблицы в запросе, какие поля, кто с кем связывается и т.д. Потом из этого собирать объект.

Проблема что типы не выводятся

А как они выведутся, если информация о том, что вернёт sql есть только в рантайме. ОРМы типа хибера и сделаны, потому что типизированные язычки не могут классы делать в рантайме им всё заранее надо описывать. Тут становится не понятно, нахрена тебе ts и типизация, получишь те же орм классы только с боку.

тоже игнорит точечную нотацию

Иметь имена с точками - такое себе удовольствие.

crutch_master ★★★★★
()
Ответ на: комментарий от crutch_master

Эх. Сколько проблем из-за дизайна протокола в виде языка SQL

pornandme
() автор топика
Ответ на: комментарий от level1

Замечу, что таблица это не реляция. Реляция это множество кортежей. То есть одинаковый кортеж считается за один в силу самого понятия множества. Тогда как таблица это мультимножество записей. Иначе говоря вхождения одинаковых записей различаются.

Чтобы правильно смоделировать реляцию таблицей последняя должна иметь первичный ключ.

Psilocybe ★★★★
()
Последнее исправление: Psilocybe (всего исправлений: 1)
Ответ на: комментарий от deep-purple

менеджеры

Менеджеры только подрывают процесс разработки.

Да, в те времена о тестировании не задумывались.

Тем не менее, обкатку софт проходил. И не обезьянками.

Тестирование стало частью процесса разработки из-за пренебрежения проектированием. Процессом руководят идиоты.

mord0d ★★★★★
()
Ответ на: комментарий от pornandme

Я надеялся на что-нибудь с API.

Сомневаюсь, что такие вещи делают внутри СУБД. Это не задача БД. Это уровнем выше, уровнем уже представления данных. Мне так кажется.

Как было у меня - внизу лежит SCO UNIX. Он нужен для уровня сети, в основном. Над ним лежит Pick - он нужен для хранения данных. Над ним лежит уже какие-то клиентские приложения с API и плюшками. В качестве стандартного, например, был SB+ от авторов. Я писал свой собственный клиент/сервер к нему, который общался на сокетах с ним и выдавал наружу уже подготовленные в нужном мне виде данные.

Но в кишках таких клиентов всё-равно будет что-то похожее на

Разделять столбцы разделителями и потом програмно собирать эту змею в объекты

просто вам это будет не видно уже. Вот за этот конец уже можно удобно дёргать откуда-нибудь из web-приложения, допустим. И доверить это прикладному программисту, которому даже и знать не надо про внутреннюю кухню.

А про неудобства с дублированием строк - в MultiValue можно, например, через поля корреляции автоматом выдергивать связанные данные. Формально, с точки зрения БД - будет выбрана и отдана наружу одна запись, с множеством значений.

Toxo2 ★★★
()
Ответ на: комментарий от Shadow

В каком смысле зачем? У меня вопрос не как хранить, а зачем строки по сети передаются комбинаторным взрывом, а не уникальными кусками. Вот мне надо получить из БД набор итемов со свойствами:

items = [
  {id, title, ...<всего 20 полей>, user_props:{prop1, prop2}},
  ...
  <всего 300 записей>
]

Это прямая задача, и дерево тут весьма условное. И мне на выбор дается два варианта:

  1. послать два запроса, из первого (items без user_props) вычисляем набор ids, суем во второй (user_props where id in ids), собираем локально. Всего 300х20 + 600х1 = 6600 условных единиц траффика, но зато два пинга и ручная сборка.

  2. джойн, при этом будет 600х22 = 13200 единиц траффика, без головняков, но в два раза больше.

А если свойств десять? Шо то, шо это - эскобар.

И сервер БД же ведь естественным образом обходит выборку древовидно, если на план посмотреть. Зачем он шлет по сети:

AAAAAAAAAAAAAAAAAAAA1 B1
AAAAAAAAAAAAAAAAAAAA1 B2
AAAAAAAAAAAAAAAAAAAA2 B3
AAAAAAAAAAAAAAAAAAAA2 B4

если можно было бы

AAAAAAAAAAAAAAAAAAAA1
  B1
  B2
AAAAAAAAAAAAAAAAAAAA2
  B3
  B4

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

anonymous
()

ТС, ты малость странный, не нравится тебе ORM пиши динамически генерируемый код (когда код пишет код), будут тебе и фичи все какие захочешь и руками всё писать не придётся, но это на особых извращенцев, не рекомендую в общем, если не фанишься, лучше как люди делай и через view, ИМХО тебе правильно его советуют заюзать, сразу полегчает немного.

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

Процессом руководят идиоты.

Можно сократить до

руководят идиоты

Можно сократить до

идиоты.


лучше как люди делай и через view, ИМХО тебе правильно его советуют

Следи за мыслью топикстартера:

Как вернуть длинный ряд после join?

Прислушавшись к громкому меньшинству, принял решение не испоьзовать ORM, а писать прям SQL-запросы

Сперва все пошло более-менее ровно, пока не появился JOIN. Та самая хваленая оптимизация, делающая один запрос там, где какая-нибудь ORM делает N+1

И получаем.. Херню мы получаем! Длинный ряд столбцов. С повторяющимися именами (в этих таблицах есть одноименные столбцы). А с учетом того, что заботливый драйвер postgres превращает ряды в словари, одинаковые имена просто схлопываются

SELECT goods.*, shoes.* ...

Пока обхожусь «name AS other_name», но это хрупко и утомительно

То есть он сам не понимает чего он хочет, но хочет чтобы всё было хорошо.

mord0d ★★★★★
()
Ответ на: комментарий от mord0d

Ну обычно либо краткость, либо скорость, иногда скрыто платится за это очень сложными и большими оптимизаторами (g++/clang) в которых за прикладного разраба сделали очень много работы, что позволяет сократить многословность при сохранении скорости, потому что многословность с избытком в коде самого компилятора. Под многословностью формально понимаем подробность описания того что надо делать машине. Потому на асме код быстрый, но огромный, а на python-е краткий, но медленный.

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

Потому на асме код быстрый, но огромный, а на python-е краткий, но медленный.

А ещё под асм нужен программист (желательно даже инженер, ибо он не для прикладухи (можно, но нафига) по сути), а на питоне говнокодить и условный дворник (человек без профильного образования) сможет.

mord0d ★★★★★
()
Ответ на: комментарий от anonymous

Ну так сделай сводную таблицу!

Будет у тебя

AAAA1  B1   B2
AAAA2           B3  B4

Shadow ★★★★★
()

Но мы же крутые. Обладая всей мощью SQL, делаем … LEFT JOIN …

делаем … LEFT JOIN …

крутые

«Вот и выросло поколение.» (с)

bytecode ★★
()
Ответ на: комментарий от mord0d

А ещё под асм нужен программист (желательно даже инженер, ибо он не для прикладухи (можно, но нафига) по сути), а на питоне говнокодить и условный дворник (человек без профильного образования) сможет.

Что за дичь я прочитал?

FortyTwo
()
Ответ на: комментарий от FortyTwo

Что за дичь я прочитал?

Не нравится — не ешь! :3

mord0d ★★★★★
()
Ответ на: комментарий от peregrine

быстрый, но огромный

Юноша, зачем вы на меня жалуетесь? Я очень разочарован вами. Я старый программист и мне нелепо слышать это ваше все.

Владимир

anonymous
()
Ответ на: комментарий от anonymous

Исключительно на маты в вашем исполнении и исполнении ваших подражателей. В остальном Владимиры если не кривляются, то нормально пишут, но в последнюю неделю все матюки что я видел на ЛОР-е были в исполнении Владимиров. Их трут, но ночью модераторы спят и обсуждение на пару страниц про писюны с последующим оффтопиком немного мешает флудить по теме.

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 2)
Ответ на: комментарий от mord0d

То есть он сам не понимает чего он хочет

На превой же странице разобрались что я хочу и даже как этого достичь. Хочу более структурированного ответа. Достигается встроенными функциями построения массивов и JSON-а

pornandme
() автор топика
Ответ на: комментарий от peregrine

сключительно на маты в вашем исполнении и исполнении ваших подражателей

Понятно. Но это уже не я. Я могу про писюны много фантазировать, но не матерюсь тут.

Владимир

anonymous
()
Ответ на: комментарий от pornandme

На превой же странице

У меня до сих пор первая страница.

разобрались что я хочу

Молодцы.

встроенными функциями построения массивов и JSON

:3

mord0d ★★★★★
()
Ответ на: комментарий от mord0d

Будут Vladimir_I Vladimir_II, Vladimir_III, Vladimir_IV и так далее.

peregrine ★★★★★
()
Ответ на: комментарий от mord0d

Я насчитал как минимум троих разных, хоть и не отслеживаю.

Я один. Поэт, гей, гомофоб, линуксоид, матершинник и архимандрит. Всё это я!!!

Владимир

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.