Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: есть возможность в select оперировать значениями предыдущей строки при выводе текущей?

есть выборка и условие в выборке:
with tabl as (select 1 as a_id,  0 as a
union select  2, 0 
union select  3, 1 
union select  4, 0 
union select  5, 0 
union select  6, 1 
union select  7, 0 
union select  8, 1 
union select  9, 1 
union select  10, 0 
)
select case a when 1 then 1 else 0 end as PPP, * from tabl order by a_id

но, надо дополнить условие в case так что бы смотреть, если в предыдущем случае это поле равно 1 то в текущем должно быть 0
т.е. в 9й строке должен бытб 0 в поле PPP
Ответ: ursido, спасибо большое
результат:
with tabl as (select 1 as a_id,  0 as a
union select  2, 0 
union select  3, 1 
union select  4, 0 
union select  5, 0 
union select  6, 1 
union select  7, 0 
union select  8, 1 
union select  9, 1 
union select  10, 0 
)
select case when a=1 and lag(a,1,0) over(order by a_id)=0 then 1 else 0 end as PPP, * from tabl order by a_id
Вопрос: велосипед: [select] колонки меняем со строками (заданное количество колонок и строк)

количество колонок и строк заранее известно
это мое решение:
with a as (select 1 as a, 2 as b, 3 as c, 4 as d
union select 2, 4, 6, 7
union select 3, 3, 2, 1
union select 4, 9, 8, 7
union select 5, 150, 200, 1
union select 6, 35, 234, 435
union select 7, 3, null, 234
union select 8, 4, 456, 123
order by a
)
select --(array[array_agg(a) ,array_agg(b) ,array_agg(c) ,array_agg(d)]),
unnest((array[array_agg(a) ,array_agg(b) ,array_agg(c) ,array_agg(d)])[1:50][1:1]) as a, 
unnest((array[array_agg(a) ,array_agg(b) ,array_agg(c) ,array_agg(d)])[1:50][2:2]), 
unnest((array[array_agg(a) ,array_agg(b) ,array_agg(c) ,array_agg(d)])[1:50][3:3]),
unnest((array[array_agg(a) ,array_agg(b) ,array_agg(c) ,array_agg(d)])[1:50][4:4]),
unnest((array[array_agg(a) ,array_agg(b) ,array_agg(c) ,array_agg(d)])[1:50][5:5]),
unnest((array[array_agg(a) ,array_agg(b) ,array_agg(c) ,array_agg(d)])[1:50][6:6]),
unnest((array[array_agg(a) ,array_agg(b) ,array_agg(c) ,array_agg(d)])[1:50][7:7]),
unnest((array[array_agg(a) ,array_agg(b) ,array_agg(c) ,array_agg(d)])[1:50][8:8])
from a 
ищу способы по проще
Ответ: Legushka,

для транспонирования есть какие--то extension--ы [ранее известные как contrib--ы]

но вот так ещё можно
+
with a (a,b,c,d) as (select * FROM (values( 1, 2,3 ,4
),( 2, 4, 6, 7
),( 3, 3, 2, 1
),( 4, 9, 8, 7
),( 5, 150, 200, 1
),( 6, 35, 234, 435
),( 7, 3, null, 234
),( 8, 4, 456, 123
)
) foo
order by 1
)
, b (a,arr) AS (
select a,array[a,b,c,d]  FROM a
)
select
	unnest( (SELECT arr from b WHERE a=1 ))
	,unnest( (SELECT arr from b WHERE a=2 ))
	,unnest( (SELECT arr from b WHERE a=3 ))
	,unnest( (SELECT arr from b WHERE a=4 ))
	,unnest( (SELECT arr from b WHERE a=5 ))
	,unnest( (SELECT arr from b WHERE a=6 ))
	,unnest( (SELECT arr from b WHERE a=7 ))
	,unnest( (SELECT arr from b WHERE a=8 ))


хотя это не выглядит много проще вашего :
+
with a (a,b,c,d) as (select * FROM (values( 1, 2,3 ,4
),( 2, 4, 6, 7
),( 3, 3, 2, 1
),( 4, 9, 8, 7
),( 5, 150, 200, 1
),( 6, 35, 234, 435
),( 7, 3, null, 234
),( 8, 4, 456, 123
)
) foo
order by 1
)
, b (arr) AS (select (array[array_agg(a) ,array_agg(b) ,array_agg(c) ,array_agg(d)]) FROM a)
select
	unnest(arr[1:50][1:1])
	,unnest(arr[1:50][2:2]) 
	,unnest(arr[1:50][3:3])
	,unnest(arr[1:50][4:4])
	,unnest(arr[1:50][5:5])
	,unnest(arr[1:50][6:6])
	,unnest(arr[1:50][7:7])
	,unnest(arr[1:50][8:8])
from  b
Вопрос: UNON и один COUNT или SELECT COUNT (SEL COUNT) + (SEL COUNT) + (SEL COUNT)

Не хочу очень подробно все расписывать. Будет очень нудно и запутано.

Поэтому постараюсь кратко, но понятно.

Описание словами; Запрос возвращает количество комментов пользоватеоя. Комменты считаются с учетом параметров доступа к ПОСТУ, и с учетом доступа возможности КОММЕНТИРОВАНИЯ, а также с учетом "дружеских связей" (я у пользователя в друзьях ИЛИ пользователь у меня в друзьях - в БД есть разница между этими понятиями).

Например: У пользоватлеь1 есть пост с доступом только для друзей.

Когда Польователь1 и пользователь2 БЫЛИ друзьями, то пользователь2 оставлял комменты под постом пользователя1. Но потом пользователь1 и пользователь2 перестали дружить.

С этого момента комменты пользователя2 под постом пользователя1 (пост только для друзей, а они уже не друзья), при просмотре СВОИХ комментов (пользователь2 смотрит свои комменты), комменты пользователя2 под постом пользователя1 (ранее они БЫЛИ друзьями) НЕ СЧИТАЮТСЯ. И в дальнейшем не будут показаны.

Это я описал словами тот "кошмар" что в запросе.
---
ОтакаяВот логика. Все это работает., НО..

Есть вопрос:
Какой запрос более эффективен? Тот что плюсует каунты
select (select count(*) from... where...) + (select count(*) from... where...) + (select count(*) from... where...);


или (тут есть проблема. Я незнаю как сделать COUNT полученных строк)

select comid from... where... union select comid from... where... union select comid from... where...; 

---
1 запрос полностью с пояснениями
//все мои* коменты в моих* постах БЕЗ учета параметров доступа к постам, комментам
select (select count(*)  from coms join posts on pid=pid_coms where uid_posts=8888 and uid_coms=8888) 

+

//комменты под постами пользователей, КОТОРЫЕ У МЕНЯ* В ДРУЗЬЯХ, (посты и коменты с доступом для друзей)
(select count(*)  from frends join posts on sl_frend=uid_posts join coms on pid=pid_coms 
where uid_coms=8888 and m_frend=8888 and ((postacc=1 and postcomacc=2) or (postacc=2 and postcomacc=2) or (postacc=2 and postcomacc=1))) 

+ 

////комменты под постами пользователей, У КОТОРЫХ Я* ДРУЗЬЯХ, (посты и коменты с доступом для друзей)
(select count(*)  from frends join posts on m_frend=uid_posts join coms on pid=pid_coms
where uid_coms=8888 and sl_frend=8888 and ((postacc=1 and postcomacc=2) or (postacc=2 and postcomacc=2) or (postacc=2 and postcomacc=1)))

+

//коменты с доступом для всех (друзей и не друзей), КРОМЕ МОИХ* ПОСТОВ (потому что все мои* считаются в первои позапросе)
(select count(*)  from coms join posts on pid_coms=pid where uid_posts != 8888 and uid_coms=8888 and postacc=1 and postcomacc=1) CountMyComms;

explain такой

+----+-------------+--------+--------+-----------------------+----------+---------+---------------------+------+----------------+
| id | select_type | table  | type   | possible_keys         | key      | key_len | ref                 | rows | Extra          |         
+----+-------------+--------+--------+-----------------------+----------+---------+---------------------+------+----------------+                           
|  1 | PRIMARY     | NULL   | NULL   | NULL                  | NULL     | NULL    | NULL                | NULL | No tables used |                           
|  5 | SUBQUERY    | coms   | ref    | uid_coms,pid_coms     | uid_coms | 4       | const               |    7 |                |
|  5 | SUBQUERY    | posts  | eq_ref | PRIMARY,pid,uid_posts | PRIMARY  | 4       | mbs.coms.pid_coms   |    1 | Using where    |
|  4 | SUBQUERY    | frends | ref    | m_frend,sl_frend      | sl_frend | 4       | const               |    1 |                |
|  4 | SUBQUERY    | coms   | ref    | uid_coms,pid_coms     | uid_coms | 4       | const               |    7 |                |
|  4 | SUBQUERY    | posts  | eq_ref | PRIMARY,pid,uid_posts | PRIMARY  | 4       | mbs.coms.pid_coms   |    1 | Using where    |
|  3 | SUBQUERY    | coms   | ref    | uid_coms,pid_coms     | uid_coms | 4       | const               |    7 |                |
|  3 | SUBQUERY    | posts  | eq_ref | PRIMARY,pid,uid_posts | PRIMARY  | 4       | mbs.coms.pid_coms   |    1 | Using where    |
|  3 | SUBQUERY    | frends | ref    | m_frend,sl_frend      | sl_frend | 4       | mbs.posts.uid_posts |    1 | Using where    |
|  2 | SUBQUERY    | coms   | ref    | uid_coms,pid_coms     | uid_coms | 4       | const               |    7 |                |
|  2 | SUBQUERY    | posts  | eq_ref | PRIMARY,pid,uid_posts | PRIMARY  | 4       | mbs.coms.pid_coms   |    1 | Using where    |
+----+-------------+--------+--------+-----------------------+----------+---------+---------------------+------+----------------+
11 rows in set (0.00 sec)


2 запрос с UNION без подробного пояснения
select comid from coms join posts on pid=pid_coms where uid_posts=8888 and uid_coms=8888 

union

select comid from frends join posts on sl_frend=uid_posts join coms on pid=pid_coms where uid_coms=8888 and m_frend=8888 and ((postacc=1 and postcomacc=2) or (postacc=2 and postcomacc=2) or (postacc=2 and postcomacc=1)) 

union

select comid from frends join posts on m_frend=uid_posts join coms on pid=pid_coms where uid_coms=8888 and sl_frend=8888 and ((postacc=1 and postcomacc=2) or (postacc=2 and postcomacc=2) or (postacc=2 and postcomacc=1)) 

union

select comid from coms join posts on pid_coms=pid where uid_posts != 8888 and uid_coms=8888 and postacc=1 and postcomacc=1;

+-------+
| comid |
+-------+
|  1300 |
|  1319 |
|  1325 |
|  1321 |
|  1296 |
|  1326 |
+-------+
6 rows in set (0.00 sec)

Выдает правильные результаты, НО КАК сделать COUNT строк? я не знаю.

+----+--------------+----------------+--------+-----------------------+----------+---------+---------------------+------+-------------+
| id | select_type  | table          | type   | possible_keys         | key      | key_len | ref                 | rows | Extra       |
+----+--------------+----------------+--------+-----------------------+----------+---------+---------------------+------+-------------+
|  1 | PRIMARY      | coms           | ref    | uid_coms,pid_coms     | uid_coms | 4       | const               |    7 |             |
|  1 | PRIMARY      | posts          | eq_ref | PRIMARY,pid,uid_posts | PRIMARY  | 4       | mbs.coms.pid_coms   |    1 | Using where |
|  2 | UNION        | coms           | ref    | uid_coms,pid_coms     | uid_coms | 4       | const               |    7 |             |
|  2 | UNION        | posts          | eq_ref | PRIMARY,pid,uid_posts | PRIMARY  | 4       | mbs.coms.pid_coms   |    1 | Using where |
|  2 | UNION        | frends         | ref    | m_frend,sl_frend      | sl_frend | 4       | mbs.posts.uid_posts |    1 | Using where |
|  3 | UNION        | frends         | ref    | m_frend,sl_frend      | sl_frend | 4       | const               |    1 |             |
|  3 | UNION        | coms           | ref    | uid_coms,pid_coms     | uid_coms | 4       | const               |    7 |             |
|  3 | UNION        | posts          | eq_ref | PRIMARY,pid,uid_posts | PRIMARY  | 4       | mbs.coms.pid_coms   |    1 | Using where |
|  4 | UNION        | coms           | ref    | uid_coms,pid_coms     | uid_coms | 4       | const               |    7 |             |
|  4 | UNION        | posts          | eq_ref | PRIMARY,pid,uid_posts | PRIMARY  | 4       | mbs.coms.pid_coms   |    1 | Using where |
| NULL | UNION RESULT | <union1,2,3,4> | ALL    | NULL                  | NULL     | NULL    | NULL                | NULL |             |
+----+--------------+----------------+--------+-----------------------+----------+---------+---------------------+------+-------------+
11 rows in set (0.00 sec)


Если UNION более ресурсоемкая операция, то надо использовать первый запрос. Но если второй (с UNION`ами) будет легче для системы, то предпочтительней его использовать. Но я не знаю как в нем сделать КАУНТ строк.

Желательно в коде обойтись БЕЗ оличества возвращаемых строк, а напрямую получить КОЛИЧЕСТВО.
---
COUNT(*) COUNT(FEILD) уже знаю .
---
или я слишком дотошно подхожу к запросам. Можно же делать как нибудь, чтоб оно как-то работало.

На что нужно обращать внимание в explain ?
Ответ: вот запрос с union
 select count(comid) from (select comid from coms join posts on pid=pid_coms where uid_posts=8888 and uid_coms=8888 

    union
    select comid from frends join posts on sl_frend=uid_posts join coms on pid=pid_coms 
    where uid_coms=8888 and m_frend=8888 and ((postacc=1 and postcomacc=2) or (postacc=2 and postcomacc=2) or (postacc=2 and postcomacc=1)) 

    union 
    select comid from frends join posts on m_frend=uid_posts join coms on pid=pid_coms 
    where uid_coms=8888 and sl_frend=8888 and ((postacc=1 and postcomacc=2) or (postacc=2 and postcomacc=2) or (postacc=2 and postcomacc=1)) 

    union 
    select comid from coms join posts on pid_coms=pid 
    where uid_posts != 8888 and uid_coms=8888 and postacc=1 and postcomacc=1) a;

    EXPLAIN
    +----+--------------+----------------+--------+-----------------------+----------+---------+---------------------+------+------------------------------+
    | id | select_type  | table          | type   | possible_keys         | key      | key_len | ref                 | rows | Extra                        |
    +----+--------------+----------------+--------+-----------------------+----------+---------+---------------------+------+------------------------------+
    |  1 | PRIMARY      | NULL           | NULL   | NULL                  | NULL     | NULL    | NULL                | NULL | Select tables optimized away |
    |  2 | DERIVED      | coms           | ref    | uid_coms,pid_coms     | uid_coms | 4       |                     |    7 |                              |
    |  2 | DERIVED      | posts          | eq_ref | PRIMARY,pid,uid_posts | PRIMARY  | 4       | mbs.coms.pid_coms   |    1 | Using where                  |
    |  3 | UNION        | coms           | ref    | uid_coms,pid_coms     | uid_coms | 4       |                     |    7 |                              |
    |  3 | UNION        | posts          | eq_ref | PRIMARY,pid,uid_posts | PRIMARY  | 4       | mbs.coms.pid_coms   |    1 | Using where                  |
    |  3 | UNION        | frends         | ref    | m_frend,sl_frend      | sl_frend | 4       | mbs.posts.uid_posts |    1 | Using where                  |
    |  4 | UNION        | frends         | ref    | m_frend,sl_frend      | sl_frend | 4       |                     |    1 |                              |
    |  4 | UNION        | coms           | ref    | uid_coms,pid_coms     | uid_coms | 4       |                     |    7 |                              |
    |  4 | UNION        | posts          | eq_ref | PRIMARY,pid,uid_posts | PRIMARY  | 4       | mbs.coms.pid_coms   |    1 | Using where                  |
    |  5 | UNION        | coms           | ref    | uid_coms,pid_coms     | uid_coms | 4       |                     |    7 |                              |
    |  5 | UNION        | posts          | eq_ref | PRIMARY,pid,uid_posts | PRIMARY  | 4       | mbs.coms.pid_coms   |    1 | Using where                  |
    | NULL | UNION RESULT | <union2,3,4,5> | ALL    | NULL                  | NULL     | NULL    | NULL                | NULL |                              |
    +----+--------------+----------------+--------+-----------------------+----------+---------+---------------------+------+------------------------------+
    12 rows in set (0.00 sec)
Вопрос: select из вьюхи, которую только что alter'нули в другом аттаче

hi all.

Народ, проверьте, плз, у себя на пустой базе вот это:

isql-1.

C:\MIX\firebird\QA\fbt-repo\tmp>isql /3255:e25
Database: /3255:e25, User: SYSDBA
SQL> create table t(a integer, b integer, c integer);
SQL> commit;
SQL> insert into t values(1,2,3);
SQL> commit;
SQL> create view v(a, b) as
CON> select a, b from t;
SQL> commit;
SQL> select * from v;

A B
============ ============
1 2

isql-2.

SQL> select * from v;

A B
============ ============
1 2

SQL> commit;

isql-1.

SQL> alter view v(a, b, c) as
CON> select a, b, c from t;
SQL> commit;

isql-2.

SQL> select * from v;

ВОПРОС. Что у вас будет выведено в результате последнего селекта в isql-2 ?
Ответ: Странно как-то. Есть , и к нему был сбацан тест, который уже несколько дней почему-то проваливается.

И судя по итогам, которые показаны на этих страницах:



-- транзакция коннекта-2 не видит обновленных метаданных.
Но и приведенный выше isql-сценарий, и вот этот питонский скрипт (а тесты прокручиваются питоном):
+
import fdb

print fdb.__version__

att1=fdb.connect(dsn='/3255:e25',user='SYSDBA',password='masterkey')
att2=fdb.connect(dsn='/3255:e25',user='SYSDBA',password='masterkey')

trn1=att1.trans()
cur1=trn1.cursor()

cur1.execute("create table t(a int, b int, c int)")   # att_12, tra_4
cur1.execute("create view v as select a,b from t")
trn1.commit()

cur1.execute("insert into t values(1,2,3)")           # att_12, tra_5
cur1.execute("select * from v")

for c in cur1.fetchall():
    print(c)

trn1.commit()

trn2=att2.trans()
cur2=trn2.cursor()
cur2.execute("select * from v")                       # att_13, tra_7
trn2.commit()

cur1.execute("alter view v as select a, b, c from t") # att-12, tra_8
trn1.commit()

cur2.execute("select * from v")                       # att_13, tra_9

for c in cur2.fetchall():
    print(c)
-- стопудово говорят, что "всё гут".

Я смог воспроизвести "слепоту" второго коннекта только извратным способом:
+
set term ^;
execute block as
begin
execute statement 'drop view v';
when any do begin end
end
^
set term ;^
commit;

recreate table t(a integer, b integer, c integer);
commit;
insert into t values(1,2,3);
commit;

recreate view v(a, b) as
select a, b from t;
commit;

set transaction read committed; -- no wait;

select current_connection as this_att, current_transaction as this_trn, v.* from v;

set term ^;
execute block returns(this_att int, this_trn int, a int, b int, c int) as
begin
for
execute statement ('select current_connection, current_transaction, v.* from v')
on external 'localhost:'||rdb$get_context('SYSTEM', 'DB_NAME')
as user 'SYSDBA' password 'masterke'
into this_att, this_trn, a, b
do suspend;

execute statement 'alter view v as select a, b, c from t' with autonomous transaction;

for
execute statement ('select current_connection, current_transaction, v.* from v')
on external 'localhost:'||rdb$get_context('SYSTEM', 'DB_NAME')
as user 'SYSDBA' password 'masterke'
-- role 'r2'
with autonomous transaction
into this_att, this_trn, a, b
do suspend;

end
^
set term ;^
Этот код покажет следующее:
 THIS_ATT     THIS_TRN            A            B
========= ============ ============ ============
2 14 1 2


THIS_ATT THIS_TRN A B C
========= ============ ============ ============ ============
3 16 1 2 <null>
3 18 1 2 <null>

Но терзают смутные сомнения, отчего тест, прогоняемый питоном, тоже "вдруг" слепой. Причём, только в одном месте - "ТАМ", на тестопрогонной тачке. У себя я проверял на двух машинах, 32 и 64 разр., на всех трёх арх-рах. И везде всё работает.

Загадко какое-то...
Вопрос: UNION работает дольше, чем 3 SELECT по отдельности.

Делаю отчет по 3 событиям собирая строки тремя разными SELECT.

По отдельности каждый из SELECT работают меньше секунды,
а объединенные в один запрос оператором UNION выполняются уже пол минуты.

Догадываюсь, что запросы криво составлены, индексов не хватает.
Оптимизатор видя их вместе ошибается с выбором индексов,
может быть есть легкий способ заставить его делать все запросы независимо и по отдельности.
Или еще как то оптимизировать объединенный запрос.

Спасибо.

+
# accept
(select
item_offer.id as item_offer_id,
item.category_id as category_id,
ifnull(item.item_group_id,offer_item_group.item_group_id) as item_group_id,
round(if(item_offer.vat = 0, item_offer.amount*1.18, item_offer.amount),2) as "val_0_sum",
0 as "val_1_sum",
0 as "val_2_sum",
date(offer.last_accept_date) as `date`
FROM equipment.item_offer item_offer

join equipment.offer on (offer.id = item_offer.offer_id)
left join 
	(	select offer_accept.offer_id as offer_id
		from equipment.offer_accept 
		where offer_accept.allow <> 1) offer_accepted on offer_accepted.offer_id = offer.id

join equipment.item on (item.id = item_offer.item_id)
left join ( SELECT 
item_offer.offer_id as offer_id,
max(item.item_group_id) as item_group_id
FROM equipment.item_offer item_offer 
join equipment.item item on (item.id = item_offer.item_id)
group by item_offer.offer_id )offer_item_group on
 (offer_item_group.offer_id = item_offer.offer_id)
where  
offer.deleted = 0 and
 item_offer.state  not in ('DECLINED','MISSED') and
 offer_accepted.offer_id is null and
 offer.last_accept_date is not null
)

#payment
union all (SELECT 
item_offer.id as item_offer_id,
item.category_id as category_id,
ifnull(item.item_group_id,offer_item_group.item_group_id) as item_group_id,
0 as "val_0_sum",
round(if(item_offer.vat = 0, item_offer.amount*1.18, item_offer.amount)*offer_payment.amount/offer_sum.offer_sum,2) as "val_1_sum",
0 as "val_2_sum",
offer_payment.payment_date as `date`
FROM equipment.item_offer item_offer
join equipment.offer on (offer.id = item_offer.offer_id)
join (SELECT 
	 offer.id as offer_id, 
     sum(if(item_offer.vat = 0, item_offer.amount*1.18, item_offer.amount)) as offer_sum
FROM equipment.item_offer item_offer
join equipment.offer offer on (item_offer.offer_id = offer.id )
where 
 offer.deleted = 0 and
 item_offer.state not in ('DECLINED','MISSED')
group by offer.id)offer_sum on (offer_sum.offer_id = item_offer.offer_id)
join equipment.item on (item.id = item_offer.item_id)
join equipment.offer_payment offer_payment on (offer_payment.offer_id = item_offer.offer_id) 
left join ( SELECT 
item_offer.offer_id as offer_id,
max(item.item_group_id) as item_group_id
FROM equipment.item_offer item_offer 
join equipment.item item on (item.id = item_offer.item_id)
group by item_offer.offer_id )offer_item_group on
 (offer_item_group.offer_id = item_offer.offer_id)
where  
offer.deleted = 0 and
 item_offer.state  not in ('DECLINED','MISSED') and
 offer_payment.payment_date is not null
#delivery
)
UNION ALL
(
SELECT 
item_offer.id as item_offer_id,
item.category_id as category_id,
ifnull(item.item_group_id,delivery_item_group.item_group_id) as item_group_id,
0 as "val_0_sum",
0 as "val_1_sum",
round(if(item_offer.vat = 0, item_offer.price*delivery_item.delivered_count*1.18, item_offer.price*delivery_item.delivered_count),2) as "val_1_sum",
date(delivery.date) as `date`
FROM equipment.item_offer item_offer
join equipment.delivery_item delivery_item on (item_offer.id = delivery_item.item_offer_id)
join equipment.delivery delivery on (delivery.id = delivery_item.delivery_id)
join equipment.item on (item.id = delivery_item.item_id)
left join ( SELECT 
delivery_item.delivery_id as delivery_id,
item_offer.offer_id as offer_id,
max(item.item_group_id) as item_group_id
FROM equipment.delivery_item delivery_item
join equipment.item_offer item_offer on (item_offer.id = delivery_item.item_offer_id)
join equipment.delivery delivery on (delivery.id = delivery_item.delivery_id)
join equipment.item on (item.id = delivery_item.item_id)
group by delivery_item.delivery_id, item_offer.offer_id )delivery_item_group on
 (delivery_item_group.delivery_id = delivery_item.delivery_id) and (delivery_item_group.offer_id = item_offer.offer_id)
where delivery.delivered = 1 
and delivery_item.delivered_count > 0 
)
Ответ:
alex564657498765453
и вопрос остаёться в силе, зачем групировку делать? то-есть у тебя этот айди либо нету, либо такойже как для любого елемента группы?? тоесть тебе по сути нужен любой елемент где не нулл требуемый айдишник.


Эту группировку я то же убрал тем, ввел новое поле: item.tmp_item_group_id и заранее его вычисляю,
если нет значения "номера группы" в основном item.item_group_id .

Вот такой процедурой:
update equipment.item 
join equipment.item_offer item_offer on (item.id = item_offer.item_id)
left join ( SELECT 
                          item_offer.offer_id as offer_id,
                          max(item.item_group_id) as item_group_id
              FROM equipment.item_offer item_offer 
              join equipment.item item on (item.id = item_offer.item_id)
              group by item_offer.offer_id )offer_item_group on
             (offer_item_group.offer_id = item_offer.offer_id)
set item.tmp_item_group_id = offer_item_group.item_group_id
where 
item.item_group_id is null 
and
item.tmp_item_group_id is null;


Сумму счета offer_sum.offer_sum вычисляю то же заранее.

И отчет становится быстрее.
Вопрос: Записать результат SELECT в "переменную" для дальнейшего использования в других запросах

Добрый день! Прошу не пинать, в SQL новичек.

С горем пополам составил запрос который выводит необходимые мне данные в виде таблицы, но даже закрытыми глазами видно какой он кривой.
select 
public.sduser.ciid,public.sduser.lastname,public.sduser.firstname,public.sduser.middlename,
public.aaacontactinfo.landline,public.aaacontactinfo.mobile,
public.requester.attribute_1501,public.sduser.userid
FROM 
public.aaacontactinfo,public.sduser,public.requester 
where 
public.aaacontactinfo.contactinfo_id=(SELECT user_id FROM aaauser WHERE first_name='АЗК-45') and 
public.sduser.userid=(SELECT user_id FROM aaauser WHERE first_name='АЗК-45') and 
public.requester.ciid=(SELECT ciid From public.sduser WHERE public.sduser.userid=(SELECT user_id FROM aaauser WHERE first_name='АЗК-45'))


Первое что бросается в глаза и на мой неумелый взгляд стоит убрать трижды выполняемый поздапрос (SELECT user_id FROM aaauser WHERE first_name='АЗК-45')

если расскажите как это запрос сократить и упростить буду очень благодарен.

Ну а пока что для меня главный вопрос как записать результат выполнения подзапроса SELECT user_id FROM aaauser... в переменную для дальнейшего использования.

Ссылки на инструкции для чайников приветствуются
Ответ: Для начала, перемести подзапрос в WITH. Вместо "=" желательно IN (или =ANY()) использовать, так как подзапрос может вернуть несколько значений user_id.
WITH
  users AS  (SELECT user_id FROM aaauser WHERE first_name='АЗК-45')
SELECT 
public.sduser.ciid,public.sduser.lastname,public.sduser.firstname,public.sduser.middlename,
public.aaacontactinfo.landline,public.aaacontactinfo.mobile,
public.requester.attribute_1501,public.sduser.userid
FROM 
public.aaacontactinfo,public.sduser,public.requester 
where 
public.aaacontactinfo.contactinfo_id IN (SELECT user_id FROM users) 
and public.sduser.userid IN (SELECT user_id FROM users) 
and public.requester.ciid=(SELECT ciid From public.sduser WHERE public.sduser.userid IN (SELECT user_id FROM users))


Но что это, после WHERE написано??? Смысла я не понял.
Вопрос: insert into tab1 (id, name) (select nextval('seq'), name from tab2) ругается на pk

Коллеги, подскажите по постгресу пожалуйста.
Копирую строки из таблицы в таблицу, хочу брать id из сиквенса.
Запрос из сабжа ругается на нарушение уникальности.
вообще
select nextval('seq'),name from tab2
дает
1,name1
1,name2
...
не понятно почему не увеличивается счетчик последовательности, оракл работает по другому, подскажите что с постгресом делать в такой ситуации. Спасибо!
Ответ: Maxim Boguk, спасибо, поутру разобрался, может пригодится:
create table tab1 (id INTEGER, name VARCHAR(10) );
CREATE SEQUENCE seq_test INCREMENT 1 START 1;
create table tab2 (id INTEGER, name VARCHAR(10) );
insert into tab1 ( id, name ) (select nextval('seq_test'), 'name1');
insert into tab1 ( id, name ) (select nextval('seq_test'), 'name2');
insert into tab1 ( id, name ) (select nextval('seq_test'), 'name3');
select * from tab1;

сначала так (работает правильно)
insert into tab2 ( id, name ) (select nextval('seq_test'), name from tab1 );

потом так (работает не правильно)
insert into tab2 ( id, name ) (select (select nextval('seq_test')), name from tab1 );

итого
select * from tab2;

id name
4 name1
5 name2
6 name3
7 name1
7 name2
7 name3
Вопрос: dbms_xplan.display_cursor User has no SELECT privilege on V$SESSION

доброе время суток народ.

есть юзер который должен смотреть планы запроса с помощью dbms_xplan.display_cursor.
Юзеру были даны права на селект из v$session, v$sql_plan и v$sql_plan_statistics_all

автор
The table function DISPLAY_CURSOR requires to have select privileges on the following fixed views: V$SQL_PLAN, V$SESSION and V$SQL_PLAN_STATISTICS_ALL.


SQL> select * from user_tab_privs_recd;

OWNER                          TABLE_NAME                     GRANTOR                        PRIVILEGE                                GRA HIE
------------------------------ ------------------------------ ------------------------------ ---------------------------------------- --- ---
SYS                            DBMS_SNAPSHOT                  SYS                            EXECUTE                          NO  NO
SYS                            V_$SQL_PLAN                    SYS                            SELECT                           NO  NO
SYS                            V_$SQL_PLAN_STATISTICS_ALL     SYS                            SELECT                           NO  NO
SYS                            V_$SESSION                     SYS                            SELECT                           NO  NO

SQL> select * from table(dbms_xplan.display_cursor);

PLAN_TABLE_OUTPUT
---------------------------------------------------------------

User has no SELECT privilege on V$SESSION



но dbms_xplan.display_cursor упорно не хочет показвать план и говорит что User has no SELECT privilege on V$SESSION

с селектом из v$session тоже все в порядке, права есть
Ответ: 123йй,

все есть кроме селекта на v$sql

сейчс глянул доку еще раз

автор
Security Model

The table function DISPLAY_CURSOR requires to have select privileges on the following fixed views: V$SQL_PLAN, V$SESSION and V$SQL_PLAN_STATISTICS_ALL.


Usage Notes

To use the DISPLAY_CURSOR functionality, the calling user must have SELECT privilege on the fixed views V$SQL_PLAN_STATISTICS_ALL, V$SQL and V$SQL_PLAN, otherwise it shows an appropriate error message.



попросил дба чтоб дали права на селект из v$sql
Вопрос: Важный вопрос по SELECT *

проблема следующая

select * from TABLE partition P1
выдает 53 строки.

select count(*) from TABLE partition P1
выдает 57 строк.

4 строки потерялось.

Проблема связана с чем-то тем что моя TABLE имеем больше 255 столбцов.

Т.е.
select COL1,COL2,...COL255 from TABLE partition P1 вернет 57 строк как и есть, а
select COL1,COL2,...COL255, COL256 уже потеряет строки.

Притом теряются строки не только для вывода на экран

create table TABLE_TEMP as
select * from TABLE partition P1

вставит все те же 53 строки.

подскажите что э то может быть?
Ответ:
4wel
Vadim Lejnin,

select 1 from table partition p1;
select 1,.....,255 from table partition p1;
select 1,.....,255,256 from table partition p1;

все четко, везде вернулись все 57 строк

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production

Может VPD настроена?
Вопрос: for select into do select

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

Такой запрос работает очень долго
select 
  t.date_doc, 
  sum(t.sum_doc) 
from table t
where t.date_doc in (select t.date_doc from table t where t.sent_date>=dateadd(day, -1, CURRENT_DATE and t.sent_date<CURRENT_DATE )
group by 1;


А такой выдает сообщение об ошибке
set term ^;

execute block as
declare variable doc_date_in date;

begin
  for select 
    t.date_doc
  from table t
  where t.sent_date>=dateadd(day, -1, CURRENT_DATE and t.sent_date<CURRENT_DATE 
  into :doc_date_in do
    select 
      t.date_doc,
      sum(t.sum_doc)
    from table t
    where t.date_doc=:doc_date_in
    group by 1;
end^

set term ;^
Ответ: stelvic,

Спасибо всем.
Заработало как надо и ощутимо быстрее.

set term ^;

execute block returns (DD Date, S float) as
declare variable doc_date_in date;

begin
  for select t.date_doc from table t
  where t.sent_date between dateadd(day, -1, CURRENT_DATE) and CURRENT_DATE
  group by 1
  into :doc_date_in do
    for select
      t.date_doc,
      sum(t.sum_doc)
    from table t
    where t.date_doc=:doc_date_in
    group by 1
    into :DD, :S do
    suspend;
end^

set term ;^