Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Запрос SELECT c игнорирование массива значений

Как в VBA сделать запрос с помощью оператора SELECT который игнорировал бы целый массив (динамический) значений?
Ответ: Capi, ltv_1953, большое спасибо
Вопрос: Select из Exec

Добрый день!
Задача такая: пользователь вводит какой то запрос на выборку , необходимо программно манипулировать этими данными (сортировка, группировка и т.д.)
Проблема в том что не могу получить Select из этого массива. Идея такова:
Select * from ( @какой то запрос юзера) t order by ...

Если запрос простой, то проблем нет, но если там объявляют переменные и т.п. то таким методом данные не получишь.
Попробовал сделать запрос через Exec
Declare @STR nvarchar(max)
Set @STR='@@какой то запрос юзера'
Exec (@STR)

Так данные выбираются, но я не могу использовать SELECT, а очень надо. Можно конечно вставить Exec (@STR) во временную таблицу и с ней работать, но для ее создания нужно знать структуру полученной выборки.
Подскажите, пожалуйста, как такое реализовать.
Ответ: вообще то, лучше так не делать и не давать такую возможность пользователям.
Вопрос: Подскажите варианты формирование списка двух DBComboBox с двух таблиц

Есть две таблицы «GOV_ETALON» и «REGISTER_ETALON», в этих таблицах есть данные о фирме-изготовителе, и данные о сотруднике. Эти данные могут повторяться.
Чтобы не набирать их по новому, как посоветовали, вместо DBComboBox использовать DBLookupComboBox и дополнительный DataSet для формирования автоматического формирования списка.
Итак, есть таблица «GOV_ETALON» в ней поля
- «фирма-изготовитель»
- «фамилия»
- «имя»
- «ученая степень»
- «ученое звание»
- «должность»


Итак, есть таблица «REGISTER_ETALON» в ней поля
- «фирма-изготовитель»
- «фамилия»
- «имя»
- «отчество»
- «телефон»
- «e-mail»

На каждой из двух форм, будет по два DBLookupComboBox (для фирмы и инф. о сотруднике)
Получается так, что в запросе:

select distinct(KEEP_LAST_NAME), KEEP_NAME, KEEP_DEGREE, KEEP_RANK, KEEP_POSITION
 from GOV_ETALON where KEEP_LAST_NAME is not null
union all
select distinct(KEEP_LAST_NAME), KEEP_NAME, KEEP_PATRONYMIC, KEEP_TELEPHONE, KEEP_E_MAIL from REGISTER_ETALON where KEEP_LAST_NAME is not null
union all
select distinct(KEEP_ORGANIZATION),'','','','' from GOV_ETALON where KEEP_ORGANIZATION is not null
union all
select distinct(STORED_ETALON),'','','','' from REGISTER_ETALON where STORED_ETALON is not null

значение поля "KEEP_ORGANIZATION", в результате попадает в поле "KEEP_LAST_NAME". и "KEEP_PATRONYMIC" забивается полем "KEEP_DEGREE".

Да и список из сотрудников наверное должен как-то быть уникальным хотябы по «фамилии» и «имени», которое должно попадать в список DBLookupComboBox

Как быть? Или все таки использовать DBComboBox с дополнительными запросами и формировании массивов?

Заранее спасибо
Ответ: Dimitry Sibiryakov,

можно сделать что-то типа:
select KEEP_LAST_NAME, KEEP_NAME, KEEP_PATRONYMIC, KEEP_TELEPHONE, KEEP_E_MAIL,
null as KEEP_DEGREE, null as KEEP_RANK, null as KEEP_POSITION from REGISTER_ETALON
union
select KEEP_LAST_NAME, KEEP_NAME, null as KEEP_PATRONYMIC, null as KEEP_TELEPHONE, null as KEEP_E_MAIL,
KEEP_DEGREE, KEEP_RANK, KEEP_POSITION from GOV_ETALON

результат туда-сюда и не впечатляет.

Но чего мудрить, сделаю:
Создам таблицу-справочник сотрудников, в которой будет хранится полная инф-я о сотрудниках (званния, тел., e-mail и т.д.).

На двух формах, на параметрах "Фамилия" поставить DBEdit, под ним поставить DBLookUpComboBox.
Пользователь при добавлении новой детали, открывает DBLookUpComboBox, в списке которого хранится ФИО. Если такая ФИО есть в справочнике, то при ее выборе, я запросом, достаю из справочника дополнительные значения параметров (тел., e-mail и т.д.), и вставляю их в соответствующие окошки на форме. Если такой ФИО нет, то он просто заполняет все параметры сотрудника (ФИО, звания и т.д.).
При сохранении в записи (детали), программа проверяет, если сотрудник с таким ФИО в справочнике. Если есть программа его не добавляет в справочник, если нет, то идет пополнение справочника новым сотрудником.

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

Уважаемые, добрый день!

Хочу спросить, есть ли для MySQL возможность сделать такой запрос:
Допустим есть 2 таблицы
Table tab1 (
   id     SERIAL
)

Table tab2 (
   id      SERIAL,
   tab1ID  BIGINT UNSIGNED NOT NULL,
   relData CHAR(10),
   FK tab1ID -> tab1.id
)


И мне надо вставить в Tab2, несколько строк. Т.е. tab1ID у них один, а вот relData - заданное множество.
Т.е. если это попробовать выразить корявым SQL запросом для наглядности, то вот:
INSERT INTO tab2 (tab1ID, relData) 
SELECT  aa.id, bb.data
FROM  Tab1      AS aa,
     (SELECT  "data1" AS data
         UNION
      SELECT  "data2" AS data
         UNION
      SELECT  "data3" AS data
              ) AS bb
WHERE aa.id=4

Даже не знаю, корректен ли такой запрос, написал его просто для иллюстрации вопроса.
Подскажите пожалуйста, как такую задачу решить?
Ответ:
Akina
нужен только у первой строки - то есть беды большой не будет, но и толку никакого, алиасы во втором и последующих запросах игнорятся, а текст длиннее...

С этим сталкивался именно вопросом. Когда например в одном запросе выбирал более - менее разнородные данные. По типу:
SELECT aa.id /*0*/, bb.data /*1*/
FROM (
    SELECT   tab1.id AS id, tab2.data AS data
UNION 
    SELECT   tab3.id AS id, tab5.info AS data
)

То в php коде при обработке результата конструкцией:
while($cur=mysqli_fetch_array($result)){
   echo $cur[0].', '.$cur[1].'<br>';
}

Если не во всех блоках union указывать алиасы для столбцов, то результат запросом выбирался верный, а вот обработка таким образом давала какие-то непредсказуемые результаты. То там, то сям появлялись пустые строки вместо данных.
Я думаю это может из-за того, что php видя разные названия столбцов в выборке формирует ассоциативный только массив значений или ещё что. Вроде бы помогало при этом указание делать только числовой массив:
while($cur=mysqli_fetch_array($result, MYSQLI_NUM)){
   echo $cur[0].', '.$cur[1].'<br>';
}
Вопрос: Через SELECT пройтись по другой выборке

Всем привет! У меня есть вот такой запрос (пример):
with a as ( ... ), -- какая-то выборка
select (
(select id from table1)
except
(select id from table2)
from a

Вот как мне сделать так, чтобы по каждой записи из A получить массив ID-шников из table1 за исключением тех, что в table2 и их же выдать в выборке?
Ответ: Jazzis,

select *
from t1 left join t2 on t1.id = t2.id -- или не left, смотря что вам нужно
where not exists (select * from t3 where t3.id2 = t2.id2)


Учитесь мыслить не строками, а множествами целиком.
Вопрос: Select count (*) group by date

Доброго времени суток форумчане!
Подскажите пожалуйста, возможно ли в одном запросе считать количество строк по многим датам?
Например имею такой набор данных:
mysql> select no,crt_date,tobilling_date,sent_to_client,dop_prov from assistfin limit 20;
+--------+---------------------+---------------------+----------------+------------+
| no     | crt_date            | tobilling_date      | sent_to_client | dop_prov   |
+--------+---------------------+---------------------+----------------+------------+
|  50.01 | 2014-02-05 10:28:10 | 2014-02-05 14:42:35 | 2014-04-16     | 2014-09-23 |
| 123.01 | 2014-02-05 19:17:36 | 2014-03-17 18:58:05 | 2014-04-10     | 2014-06-30 |
|  51.01 | 2014-02-06 00:09:32 | 2014-03-20 16:53:46 | 2014-04-10     | 2014-06-30 |
| 124.01 | 2014-02-06 15:29:08 | 2014-03-20 17:04:42 | 2014-04-10     | 2014-06-30 |
| 230.01 | 2014-02-07 22:01:11 | 2014-03-20 16:41:03 | 2014-04-10     | 2014-06-30 |
| 252.01 | 2014-02-08 02:52:33 | 2014-03-20 16:43:03 | 2014-04-10     | 2014-06-30 |
| 123.02 | 2014-02-08 03:00:52 | 2014-03-17 18:58:10 | 2014-04-10     | 2014-06-30 |
| 213.01 | 2014-02-08 04:01:35 | 2014-03-26 19:03:01 | 2014-04-10     | 2014-09-19 |
|  55.01 | 2014-02-08 21:04:45 | 2014-03-07 18:40:46 | NULL           | 2014-06-26 |
| 126.01 | 2014-02-08 21:46:58 | 2014-09-02 18:39:36 | 2014-09-09     | 2014-09-26 |
| 284.01 | 2014-02-09 01:52:54 | 2014-06-11 19:11:06 | 2014-07-02     | 2014-07-21 |
| 261.01 | 2014-02-09 02:20:34 | 2014-03-17 20:57:39 | 2014-04-10     | 2014-06-30 |
| 318.01 | 2014-02-09 03:09:28 | 2014-03-17 20:44:25 | 2014-04-10     | 2014-06-30 |
| 225.01 | 2015-02-10 03:21:08 | 2014-03-20 16:57:56 | 2014-04-10     | 2014-06-30 |
| 248.01 | 2015-02-09 03:30:58 | 2014-03-18 18:02:21 | 2014-04-10     | 2014-06-30 |
| 178.01 | 2016-04-05 03:35:25 | 2014-03-21 17:10:12 | 2014-04-10     | 2014-06-30 |
| 184.01 | 2016-04-08 04:01:13 | 2014-03-20 16:38:02 | 2014-04-10     | 2014-06-30 |
| 320.01 | 2016-04-08 05:57:23 | 2014-03-17 20:49:19 | 2014-04-10     | 2014-06-30 |
| 230.02 | 2016-05-08 06:18:15 | 2014-03-20 16:41:08 | 2014-04-10     | 2014-06-30 |
| 325.01 | 2016-05-09 06:23:50 | 2014-03-17 20:42:04 | 2014-04-10     | 2014-06-30 |
+--------+---------------------+---------------------+----------------+------------+


На выходе нужна таблица вида:
+---------+---------+--------+-----------+---------+
| year    | Created | Passed | To client | To prov |
+---------+---------+--------+-----------+---------+
| 2016-01 |    1901 |   1879 |      1873 |    1743 |
| 2016-02 |    2192 |   2169 |      2114 |    1912 |
| 2016-03 |    2693 |   2639 |      2539 |    2309 |
| 2016-04 |    2634 |   2574 |      2273 |    1976 |
| 2016-05 |    2593 |   2497 |      1109 |     949 |
| 2016-06 |     471 |    449 |         2 |      78 |
+---------+---------+--------+-----------+---------+
Ответ:
necoro
осталось понять как это чудо работает

Да вот собсно подзапрос, который AS t, и генерит тебе список, о котором я упорно твердил... Правда, необходимость генерации его на 83 года мне кажется сомнительной...

И вторая метода - использование SUM по равенству - будет работать намного быстрее на больших массивах.
Вопрос: есть возможность в 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)
Вопрос: 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 вычисляю то же заранее.

И отчет становится быстрее.