Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / подружить DISTINCT с агрегатором / 25 сообщений из 27, страница 1 из 2
09.02.2015, 18:23
    #38875091
Electric200
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Добрый день уважаемые. В общем подскажите что я не так делаю.. Есть подзапрос
Код: plsql
1.
2.
3.
4.
5.
6.
7.
    (
                    SELECT DISTINCT ON ("OPID") "OPID", 
                           odp_agr(ARRAY[ARRAY[CAST("OPID" AS text),CAST("OPVALUE" AS text)]]) AS oparray                    
                    FROM "2343_ODP"  WHERE "2343_ODP"."DATE"="2343_GDP"."DATE" 
                    AND "2343_ODP"."DATE">='2015-02-07 18:36:01'
                    AND "2343_ODP"."DATE"<'2015-02-09 13:20:07' 
                  )


Т.е в odp_agr сейчас попадают несколько значений с одинаковым "OPID":
Код: plsql
1.
{{"120","300"},{"121","300"},{"120","300"},{"123","300"}}


А мне необходимо либо сгруппировать либо исключить повторы.
А в таком виде как я привел пример, получаю ошибку:
Код: plsql
1.
ОШИБКА:  колонка "2343_ODP.OPID" должна фигурировать в предложении GROUP BY или использоваться в агрегатной функции


Почему планировщик, при использовании в обычном запросе, понимает что необходимо выбросить "дубляжи" без каких либо группировок, а тут чего то хочет от меня? Пусть также выбросит, а что останется передаст в агрегатор.
В общем, я запутался.
...
Рейтинг: 0 / 0
09.02.2015, 18:38
    #38875107
поправил
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Electric200
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    ( 
                    SELECT --DISTINCT ON ("OPID") uyfreq gmzys[ gj[,nbcnjd
                           "OPID", 
                           odp_agr(ARRAY[ARRAY[CAST("OPID" AS text),CAST("OPVALUE" AS text)]]) AS oparray                    
                    FROM "2343_ODP"  WHERE "2343_ODP"."DATE"="2343_GDP"."DATE" 
                    AND "2343_ODP"."DATE">='2015-02-07 18:36:01'
                    AND "2343_ODP"."DATE"<'2015-02-09 13:20:07' 

                    GROUP BY "OPID"
                  )
...
Рейтинг: 0 / 0
09.02.2015, 19:09
    #38875134
Electric200
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
поправил,

Конечно, но в таком случае возвращает несколько строк.. А мне необходимо одну. Собственно весь запрос:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
SELECT
                  DISTINCT ON ( "2343_GDP"."DATE") "2343_GDP"."DATE", 
                  hstore("2343_GDP".*),
                  "2343_GDP"."POINTXY"[0] AS "POINTX",
                  EXTRACT (EPOCH FROM "2343_GDP"."DATE")          AS "DATEGPS_UNIX",
                  EXTRACT (EPOCH FROM "2343_GDP"."DATETRANS")  AS "DATETRANS_UNIX",
                  "2343_GDP"."POINTXY"[1] AS "POINTY",
                  (
                    SELECT  odp_agr(ARRAY[ARRAY[CAST("OPID" AS text),CAST("OPVALUE" AS text)]]) AS oparray FROM                
                    "2343_ODP"  WHERE "2343_ODP"."DATE"="2343_GDP"."DATE" 
                    AND "2343_ODP"."DATE">='2015-02-07 18:36:01'
                    AND "2343_ODP"."DATE"<'2015-02-09 13:20:07' 
                  )
                  FROM "2343_GDP" 
                  WHERE "2343_GDP"."DATE">='2015-02-07 18:36:01' AND "2343_GDP"."DATE"<'2015-02-09 13:20:07'
                  ORDER BY  "2343_GDP"."DATE" ASC;
...
Рейтинг: 0 / 0
09.02.2015, 19:53
    #38875153
/\/\/\/\/\/\
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Electric200,

Значит нужно сперва выбрать данные, затем исключить дубликаты и только потом агрегировать.
Как-то так:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
SELECT
  odp_agr(ARRAY[ARRAY[f1, f2]]) AS oparray
FROM ( 
SELECT DISTINCT
  CAST("OPID" AS text) AS f1,
  CAST("OPVALUE" AS text) AS f2 
FROM "2343_ODP"  
WHERE "2343_ODP"."DATE"="2343_GDP"."DATE" 
  AND "2343_ODP"."DATE">='2015-02-07 18:36:01'
  AND "2343_ODP"."DATE"<'2015-02-09 13:20:07' ) t
...
Рейтинг: 0 / 0
09.02.2015, 20:56
    #38875184
поправил
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Electric200поправил,

Конечно, но в таком случае возвращает несколько строк.. А мне необходимо одну. Собственно весь запрос:
<>
и что вам не нравится в вашем запросе ?

простите телепаты в отпуске, хрустальный шар давно не мыли, а на языке поддатых похабешников тут мало кто говорит
...
Рейтинг: 0 / 0
10.02.2015, 12:12
    #38875722
Electric200
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
поправил,
В моем запросе, мне не нравилось, что в агрегатор попадали записи с одинаковыми "DATE","OPID".
Спасибо "/\/\/\/\" за помощь. С его вариантом стало лучше.. Но потом меня начало не устраивать, что DISTINCT ON основного запроса исключает дублирование после того как выполнились все подзапросы . В итоге, куча ненужных телодвижений.
По этому, покалдовав сделал конфетку. Может кому то пригодится.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
                                    SELECT t.*,(
                                           SELECT  odp_agr(ARRAY[ARRAY[f1,f2]]) AS oparray  
                                             FROM  
                                              ( SELECT  
                                                 DISTINCT ON ("OPID") CAST("OPID" AS text) AS  f1,
                                                 CAST("OPVALUE" AS text) AS f2  
                                                FROM                
                                                "2343_ODP"  WHERE 
                                                    "2343_ODP"."DATE" = t."DATE"
                                                    AND "2343_ODP"."DATE" >= '2015-02-07 18:36:01'
                                                    AND "2343_ODP"."DATE" <  '2015-02-09 13:20:07' 
                                              )AS o)
                                                
                                            FROM 
                                                (SELECT 
                                                DISTINCT ON ( "2343_GDP"."DATE") "2343_GDP"."DATE", 
                                                hstore("2343_GDP".*),
                                                "2343_GDP"."POINTXY"[0] AS "POINTX",
                                                EXTRACT (EPOCH FROM "2343_GDP"."DATE")          AS "DATEGPS_UNIX",
                                                EXTRACT (EPOCH FROM "2343_GDP"."DATETRANS")     AS "DATETRANS_UNIX",
                                                "2343_GDP"."POINTXY"[1] AS "POINTY"
                                               
                                                FROM "2343_GDP" 
                                                WHERE "2343_GDP"."DATE">='2015-02-07 18:36:01' AND "2343_GDP"."DATE"<'2015-02-09 13:20:07'
                                                ORDER BY  "2343_GDP"."DATE" ASC)
                                         AS t;
...
Рейтинг: 0 / 0
10.02.2015, 12:13
    #38875725
Electric200
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
В итоге 130 мс . против 35 сек в моей случае) все спасибо)
...
Рейтинг: 0 / 0
10.02.2015, 12:47
    #38875811
поправил
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Electric200поправил,
В моем запросе, мне не нравилось, что в агрегатор попадали записи с одинаковыми "DATE","OPID".
<>ничего не понял
зачем вам агрегатор, если вам нужен (судя по обрывкам мысли в бреде) LIMIT 1 в кореляте, и плоское поле, а не array на выходе из корелята


ну или я опять упоротых похабеньников не понимаю -- с ними это постоянно случается

PS бред в запросах нечетал, многабукав, кг/ам
...
Рейтинг: 0 / 0
10.02.2015, 15:07
    #38875994
Electric200
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
поправил,
Вы все таки вчитайтесь в запрос наверно, поскольку лимит мне не нужен. Иначе зачем мне тогда агрегатор.
Есть две таблицы:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
  t1          t2  
DATE       DATE   OPID VALUE
111         1111      2     13
222         1111      2     13
222         1111      4     15 
333         1111      8     12
333         1111      8     12
333         3333      6     10
333         6666      1     1
444         6666      3     1
555         7777      2     2
555         7777      5     5
666 


Количество записей результат запроса, должно быть равно количеству уникальных значений t1.DATE за определенный период времени т.е "DATE". Каждая запись должна содержать массив значений "OPID","VALUE" с таблицы t2, уникальные по "DATE" и "OPID". Т.е одной t1."DATE" может соответствовать несколько несколько t2."DATE" как с одинаковыми так и с разными OPID. JOINы мне не подходят по нескольким причинам. Так какой LIMIT мальчик?)
...
Рейтинг: 0 / 0
10.02.2015, 15:19
    #38876011
поправил
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Electric200,

да я посмотрел уже по результату, чего вы деете.
криво это всё спроектировано, как архитектурка, т.е., если date это НЕ дата, а таймстамп.

какая селективность дистинкта по "OPID" внутри "DATE" ?

если их подавляется много -- то ORDER BY .. LIMIT 1 (внутри LATERAL или корелята [у вас это был бы кореля в кореляте]) будет много быстрее DISTINCT ON (если это еще не изменено самими кодерами планера -- до сих пор [9.3] DISTINCT ON был в пж убогеньким)

за подробностями -- к богику, у него где-то пдф-ка даже была по мотивам.

ЗЫ а рассказывать задачу вы не умеете, катастрофически
...
Рейтинг: 0 / 0
10.02.2015, 15:23
    #38876019
поправил
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Electric200,
PS а ты, парамоша, мало что удак, так ещё и азартный удак
...
Рейтинг: 0 / 0
10.02.2015, 15:54
    #38876056
Electric200
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
поправил,
Эй... Дата TIMESTAMP. Мне же время нужно, а не только дата. Причем тут кривизна архитектуры? Это вы решили на основании одного запроса? А остальных пару десятков?)
Селективность с DISTINCT ON не высокая.. Вероятность наличия дублей, это 0.1% из 100% на фоне общего количества записей. Но этот 0.1% процент может мне создать задержу в обработке полученных данных.
И я не пойму чего вы мне "суете" снова ORDER BY с LIMIT1 снова? Причем тут? Ведь я же в примере сказал (а вы меня похвалили за красноречивость), что одному t1."DATE" может соответствовать несколько t2."DATE" c разными "OPID" - которые заранее мне не известны. А с ORDER BY с LIMIT1 я получу одну запись с t2 с одним "OPID". И стоп.. причем тут ORDER ? У меня же
WHERE "2343_ODP"."DATE"="2343_GDP"."DATE" по чему мне сортировать? Что вы меня путаете!!!)
...
Рейтинг: 0 / 0
10.02.2015, 16:18
    #38876101
поправил
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Electric200,

если вам нужен дистинкт по таймстампу -- то вы или храните лишнее (раз вам нужен только дистинкт то и клали бы без дублей)
, или плюёте на нужное (раз берёте только часть хранимого)
короче в любом случае -- тудак
а архитектура тудака -- тудацкая
по определению
кактотак


при низкой кардинальности дешевле бегать индекс-сиком [т.е. NESTED LOOP по индексу] (реализовав его через LATERAL ORDER BY LIMIT 1), чем исполнять DISTINCT ON
...
Рейтинг: 0 / 0
10.02.2015, 16:46
    #38876164
Electric200
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
поправил,
В t2 таблице, руками проверять наличие такой записи, слишком дорогое удовольствие по сравнению использования DISTINCT ON в отдельных запросах и с учетом низкой вероятности наличия дублей. Интенсивность записи порядка 2 млн в сутки, а участие в выборке может доходить более 1 млн по отдельному селекту. Конечно все это партицировано, но вы точно меня хотите по миру пустить. _))
...
Рейтинг: 0 / 0
10.02.2015, 16:50
    #38876173
Electric200
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Electric200,
И есть еще одна цель. Писать все, что приходит. А дальше уже разбираться что нужно, а что нет.
...
Рейтинг: 0 / 0
10.02.2015, 17:00
    #38876187
поправил
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Electric200поправил,
В t2 таблице, руками проверять наличие такой записи, слишком дорогое удовольствие по сравнению использования DISTINCT ON в отдельных запросах и с учетом низкой вероятности наличия дублей. Интенсивность записи порядка 2 млн в сутки, а участие в выборке может доходить более 1 млн по отдельному селекту. Конечно все это партицировано, но вы точно меня хотите по миру пустить. _))

какбе unique -- обычное решение. при 10--12 млн в сутки несколько unique не мешают нормально писать, даже когда "это всё партицировано" по той же дате.

причем можно писать всё -- добавьте ещё поле -- "номер в моменте" в unique, по нему и фильтр брать -- хотя это лишнее усложнение-- нумеровать, а не отбрасывать.

а вот DISTINCT ON брать от лямов -- это дорогое удовольствие независимо от числа повторов (при большом -- оптимизируемо, как сказано выше [ точно от >~10^3 (возможно иногда и при ~10^2 -- "с когда" -- зависит от частоты шпинделя, и кластеризации)] -- "индекс-сиком")
...
Рейтинг: 0 / 0
10.02.2015, 17:41
    #38876239
Electric200
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
поправил,
Но на момент планирование мне почему то казалось, что наличие UNIQUE по DATE,OPID которые являются индексом - отразится на производительности, по сравнению с использованием DISTINCT ON при выборке. Но радует одно, что по сравнению с DISTINCT, что без него - на быстроту выполнения на данный момент не повлияло. Зато я перестраховался от неловких ситуаций.
Еще тогда вопрос. Как работает UNIQUE изнутри? Это тот же SELECT перед INSERT?
Спасибо!
...
Рейтинг: 0 / 0
10.02.2015, 21:19
    #38876368
поправил
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Electric200,
там внутри неонка:
CREATE UNIQUE INDEX .....
-- примерно так, т.ч. это не совсем селект из таблицы.

опасности стандартные -- очередь на unique.
т.е. долгие транзакции на вставку/update unique не приветствуются.

INSERT NOWAIT -- пока только в проекте, и на сайте желаемых публикой шняшек где-то в конце.
...
Рейтинг: 0 / 0
10.02.2015, 21:30
    #38876374
поправил
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
и да, вставка дубля, если такой unique закоммичен, просто вылетает по unique violation[если не обрабатывать]
-- просто сообщаете клиенту, что тапки нынче не его.
если автомат -- то в лог,и с концами -- скрипач не нужен.
...
Рейтинг: 0 / 0
10.02.2015, 21:53
    #38876385
NikolayV81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Electric200поправил,
Но на момент планирование мне почему то казалось, что наличие UNIQUE по DATE,OPID которые являются индексом - отразится на производительности, по сравнению с использованием DISTINCT ON при выборке. Но радует одно, что по сравнению с DISTINCT, что без него - на быстроту выполнения на данный момент не повлияло. Зато я перестраховался от неловких ситуаций.
Еще тогда вопрос. Как работает UNIQUE изнутри? Это тот же SELECT перед INSERT?
Спасибо!

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

p.s. В настройкай транзакции NO WAIT для пишуших автоматов полезная ( и я бы сказал необходимая ) штука особенно когда волнуют простои при записи.
...
Рейтинг: 0 / 0
10.02.2015, 21:59
    #38876390
Electric200
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
NikolayV81,
Та не индексы, а UNIQUE
...
Рейтинг: 0 / 0
10.02.2015, 22:27
    #38876408
NikolayV81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Electric200NikolayV81,
Та не индексы, а UNIQUE

да какая разница принцип работы одинаковый ( одно просто ещё и посылает при no wait )
...
Рейтинг: 0 / 0
10.02.2015, 23:16
    #38876426
NikolayV81
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
NikolayV81Electric200NikolayV81,
Та не индексы, а UNIQUE

да какая разница принцип работы одинаковый ( одно просто ещё и посылает при no wait )

Блин туплю, забыл про особенность Postgre, ведь открыл из поисковика http://www.postgresql.org/message-id/4A015633.9070502@gmail.com]http://www.postgresql.org/message-id/4A015633.9070502@gmail.com увидел там синтаксис для transaction с no wait, успокоился и написал а потом только дошло что в доках то другое.
...
Рейтинг: 0 / 0
11.02.2015, 01:31
    #38876477
Maxim Boguk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Electric200NikolayV81,
Та не индексы, а UNIQUE

unique реализован через unique index в postgresql

--Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
11.02.2015, 10:09
    #38876612
Electric200
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подружить DISTINCT с агрегатором
Хорошо. Успокоили. Переделаю значит. Просто изначально сравнить с UNIQUE и без, на реальных интенсивных вставках - возможности не было. Но если вы так убеждаете, что на производительности не повлияет, попробую значит.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / подружить DISTINCT с агрегатором / 25 сообщений из 27, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]