
Yaroslav
26.09.2018
21:29:48

Igor
26.09.2018
21:30:18
id | x | y | z
-------+--------------------+--------------------+--------------------
80074 | -0.516964306237286 | 0.672032968938634 | 0.530207124373227
80075 | 0.542653026928013 | -0.609808736454484 | 0.577633964816519
на выходе после перемножения этих двух строк должно быть примерно такое (лень набирать все цифры):
-0,516*0,542+0,672*-0,609 +0,53*0,578
то есть надо вытащить 3 числа из какой-то строки, потом пройтись по всей таблице, перемножая эти числа на соответствующие столбцы, потом сложить полученное для каждой строки

Google

Igor
26.09.2018
21:35:28
на самом деле, может, там и другая БД больше для этих целей подходит, но я не нашел (Кликхаус не умеет в редактирование и в реляционщину)

Yaroslav
26.09.2018
21:43:28

Igor
26.09.2018
21:43:58
да, а потом их всех сложить
https://ru.wikipedia.org/wiki/%D0%A1%D0%BA%D0%B0%D0%BB%D1%8F%D1%80%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5#%D0%90%D0%BB%D0%B3%D0%B5%D0%B1%D1%80%D0%B0%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D0%BE%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5
Вот так, если быть точным

Yaroslav
26.09.2018
21:48:15
Вот так, если быть точным
Я бы, наверное, вообще custom aggregate создал для начала, если Вам часто такое нужно.
Что-то вроде:
CREATE OR REPLACE FUNCTION product_numeric_state(numeric, numeric)
RETURNS numeric
LANGUAGE SQL IMMUTABLE
as $f$
SELECT $1 * $2;
$f$;
CREATE AGGREGATE PROD(NUMERIC) (
SFUNC = product_numeric_state,
STYPE = NUMERIC,
INITCOND = 1
);
Ну а потом уже просто:
SELECT prod(x)+prod(y)+prod(z)
FROM table;

Igor
26.09.2018
21:56:42
эм... а как это запускается в оболочке? я пробовал psql -U postgres -h 127.0.0.1 -p 5432 -d physics -f scalar.sql
ну и вот этот код в файле scalar.sql
ERROR: function "prod" already exists with same argument types, но ERROR: function prod(double precision) does not exist

Yaroslav
26.09.2018
22:03:52
Название агрегата, кстати, может быть точно такое же (prod), PostgreSQL по типу агрумента определит, какой вызывать.

Igor
26.09.2018
22:08:51
А почему на выходе одно число вместо столбца?

Google

Igor
26.09.2018
22:09:28
и какие это строки в примере перемножаются? первая и какая?
а. или дальше предлагается дальше еще одну функцию написать, которая бы проходила по всем строкам?

Yaroslav
26.09.2018
22:11:54

Igor
26.09.2018
22:12:11
столько же, сколько изначально было

Yaroslav
26.09.2018
22:12:32

Igor
26.09.2018
22:12:55
а. я смотрю вы просто все числа в каждом столбце перемножили и потом сложили?
ну ок. тогда на языке множеств без циклов формулировка: есть множество точек, из него выбрали одну конкретную, и создали второе множество пар точек. для каждой пары точек (каждая из которых представляет собой вектор) вывести скалярное произведение

Yaroslav
26.09.2018
22:15:58

Igor
26.09.2018
22:17:31
нет.
5
Если я выбираю из 1 множества одну точку, то остается 4 - значит 4 пары точек мы знаем. пятая - когда точка сама с собой перемножается

Yaroslav
26.09.2018
22:19:36
Я имел в виду "для всех точек".
Т.е. Вы хотите выбирать этот "один из векторов" в запросе?

Igor
26.09.2018
22:19:39
но вообще всего пар - 25, да
да

Yaroslav
26.09.2018
22:22:56
Тьфу. Вообще не о том подумал. ;)
Это что-то вроде:
SELECT point1.id, point2.id, (point1.x * point2.x + point1.y * point2.y + point1.z * point2.z) AS prod
FROM point AS point1
CROSS JOIN point AS point2
WHERE point1.id = нужная_точка;
CROSS JOIN — декартово произведение.

Igor
26.09.2018
22:23:36
да, ближе к правде уже
счас проверю
а prod что такое?

Yaroslav
26.09.2018
22:25:57

Google

Yaroslav
26.09.2018
22:27:06
Можете любое использовать, естественно. Аналогично "AS point1", "AS point2" — тоже alias-ы, но для таблиц.

Igor
26.09.2018
22:30:03
CREATE OR REPLACE FUNCTION product_vectors(point_id numeric)
RETURNS SETOF float
LANGUAGE SQL IMMUTABLE
as $f$
SELECT point1.id, point2.id, (point1.x * point2.x + point1.y * point2.y + point1.z * point2.z) AS prod
FROM points_table AS point1
CROSS JOIN points AS point2
WHERE point1.id = point_id;
$f$;
Вот на такое счас выводит
psql:scalar.sql:11: ERROR: return type mismatch in function declared to return double precision
DETAIL: Final statement must return exactly one column.
CONTEXT: SQL function "product_vectors"

Yaroslav
26.09.2018
22:33:07

Igor
26.09.2018
22:33:58
ну так от нее и ожидается, что вернется одна колонка чисел

Yaroslav
26.09.2018
22:35:14

Igor
26.09.2018
22:37:10
помогло
а вызывать ее как?
product_vectors(80069);
ERROR: syntax error at or near "product_vectors"
LINE 1: product_vectors(80069);

Yaroslav
26.09.2018
22:38:48
SELECT *
FROM product_vectors(80069);

Igor
26.09.2018
22:39:31
О! работает! Как надо! спасибо огромное

Yaroslav
26.09.2018
22:39:59

Igor
26.09.2018
22:45:50
А еще такой вопрос: постгрес как-то оптимизирует функции? есть ли разница в скорости, если я сначала создам через .sql-файл эту функцию, а потом из ORM буду ее вызывать, и если я сразу буду из ORM дергать этот SELECT, который внутри тела функции?

Andrey
27.09.2018
00:50:28

Terminator
27.09.2018
03:35:35
@KladovArtem будет жить. Поприветствуем!
Максим будет жить. Поприветствуем!

Mike Chuguniy
27.09.2018
06:37:59
Оставлю для истории. pgbouncer умеет авторизовывать юзеров в самой PG, без всяких файликов и проч.
Просто запросом SELECT usename, passwd FROM pg_shadow WHERE usename=$1, но для этого ему нужно будет выделить некого админского юзера, под которым pgbouncer будет хоть в базу для авторизации.
@Aytuar @uspen2018
паранойя моде вкл.
А ещё можно соорудить ф-ию с SECURITY DEFINER, которая будет дергать pg_shadow от суперпользователя и возвращать то, что нужно. Дать гранты на выполнение этой ф-ии рядовому пользователю, которому всячески ограничить запуск ф-ии, например, хостом и приложением, ну и вот это всё. И уже из пгбаунсера дёргать эту ф-ию, от имени разрешённого пользователя с разрешённого узла.
паранойя моде суспенд ин мемору.


Yaroslav
27.09.2018
06:58:34
паранойя моде вкл.
А ещё можно соорудить ф-ию с SECURITY DEFINER, которая будет дергать pg_shadow от суперпользователя и возвращать то, что нужно. Дать гранты на выполнение этой ф-ии рядовому пользователю, которому всячески ограничить запуск ф-ии, например, хостом и приложением, ну и вот это всё. И уже из пгбаунсера дёргать эту ф-ию, от имени разрешённого пользователя с разрешённого узла.
паранойя моде суспенд ин мемору.
А вот, кстати, вопрос (ко всем): Как Вы пишете SECURITY DEFINER (суперпользовательские) функции (которые могут использовать обычые users) так, чтобы это было собственно secure? Есть какой-то шаблон?


Let Eat
27.09.2018
07:33:45
Уважаемые знатоки, UPDATE t SET v=v создаёт новый тупл, внимание вопрос: нахуя так? И будет ли оно ломать HOT если поле проиндексировано?

Konstantin
27.09.2018
07:34:37

Sergey
27.09.2018
07:36:29

Google

Let Eat
27.09.2018
07:37:11

Sergey
27.09.2018
07:38:35
Это да, но вдруг нет? Строго говоря это транзакция а значит есть данне до коммита и после. Возможно да, тут есть что оптимизировать

Konstantin
27.09.2018
07:39:03

Yaroslav
27.09.2018
07:42:00

Let Eat
27.09.2018
07:43:41
Спасибо за разъяснения. назначенное лечение "не делайте так" уже успешно проигнорировано :)

Yaroslav
27.09.2018
07:50:49

Kirill
27.09.2018
07:52:56
Уважаемые, приветствую. Подскажите пожалуйста оптимальное решение для удаления из таблицы строчек в которых значение поля n одинаковое ?

Vladimir
27.09.2018
07:55:09

Kirill
27.09.2018
07:55:31

Vladimir
27.09.2018
07:58:48
именно !
Таблица большая? (Ну или по другому, страшно ли ее лочить?)

Kirill
27.09.2018
07:59:26

Vladimir
27.09.2018
08:13:07

Victor
27.09.2018
08:13:08
подскажите пожалуйста, можно ли из датывремени извлечь только время для последующего сравнения?
вроде как extract может отдельно часы, одельно минуты
но мне надо отобрать все записи для всех datetime которые после 21:00 до 9:30 утра

Vladimir
27.09.2018
08:15:22

Andrey
27.09.2018
08:15:28

Victor
27.09.2018
08:15:56
точно, спасибо :)

Kirill
27.09.2018
08:16:53

Google


Akylai
27.09.2018
08:32:17
Люди помогите понять как в одном запросе 3 суб запроса прописать
SELECT qr.dates,
sum(qr.status_0) AS status0,
sum(qr.status_1) AS status1,
sum(qr.status_2) AS status2,
sum(qr.status_3) AS status3,
sum(qr.status_4) AS status4,
gw.created,
sum(gw.activeProfiles) AS activeProfiles,
sum(gw.inactiveProfiles) AS inactiveProfiles,
gw.date,
sum(gw.cardNotSubmit) AS cardNotSubmit,
sum(gw.cardActive) AS cardActive,
sum(gw.cardRemoved) AS cardRemoved,
with qr as(SELECT date_trunc('year' :: text, tr.created) AS dates,
CASE
WHEN (tr.state = 0) THEN count(*)
ELSE (0) :: bigint
END AS status_0,
CASE
WHEN (tr.state = 1) THEN count(*)
ELSE (0) :: bigint
END AS status_1,
CASE
WHEN (tr.state = 2) THEN count(*)
ELSE (0) :: bigint
END AS status_2,
CASE
WHEN (tr.state = 3) THEN count(*)
ELSE (0) :: bigint
END AS status_3,
CASE
WHEN (tr.state = 4) THEN count(*)
ELSE (0) :: bigint
END AS status_4
FROM (gw_transactions tr)
GROUP BY (date_trunc('year' :: text, tr.created)), tr.state),
gw as(SELECT date_trunc('year' :: text, pr.created) AS created,
CASE
WHEN (pr.state = 1) THEN count(*)
ELSE (0) :: bigint
END AS activeProfiles,
CASE
WHEN (pr.state = 0) THEN count(*)
ELSE (0) :: bigint
END AS inactiveProfiles
FROM gw_profiles pr
GROUP BY (date_trunc('year' :: text, pr.created)), pr.state),
lc as(SELECT date_trunc('year' :: text, c2.created) AS date,
CASE
WHEN (c2.state = 0) THEN count(*)
ELSE (0) :: bigint
END AS cardNotSubmit,
CASE
WHEN (c2.state = 1) THEN count(*)
ELSE (0) :: bigint
END AS cardActive,
CASE
WHEN (c2.state = 3) THEN count(*)
ELSE (0) :: bigint
END AS cardRemoved
FROM gw_profiles pr
GROUP BY (date_trunc('year' :: text, c2.created)), c2.state),
GROUP BY qr.dates
ORDER BY qr.dates;
пытаюсь сделать таким способом
но увы
если сделать наоборот , сначало джоинить и потом выводить то выходят не корректные данные


Yaroslav
27.09.2018
08:48:04

Akylai
27.09.2018
08:52:01
ну и соответственно результат
хочу дописать этот запрос что бы в таком же виде получить статусы из таблицы пользователей
и карт пользователей
что бы все было в одной запросе

Yaroslav
27.09.2018
08:59:38
что бы все было в одной запросе
Ну так дописывайте. Только не изобретайте свой синтаксис при этом, WITH пишется в начале (под)запроса, а не посреди него. ;)

Andrey
27.09.2018
09:10:17
Подскажите, а это нормальная ситуация, когда pg_basebackup не скопировал файл pg_control? Бэкап снимал со стендбая.

Akylai
27.09.2018
09:26:03
не получается