#sql
#sql
Вопрос:
У меня есть два SQL-запроса. Во-первых, для этих pl — ‘IQ’, ‘SM’, ‘T2’, а во-вторых, для pl = ‘AT’, ‘VV’,’CM’. Я получаю следующую информацию —
Есть ли какая-либо возможность оптимизировать эти два запроса и объединить их в один? Информация в операторе CASE повторяется, отличается только pl.
Первый запрос:
/* Formatted on 10.7.2016 1:23:06 (QP5 v5.163.1008.3004) */
SELECT DISTINCT
pl,
SUM (
CASE
WHEN pl IN ('IQ', 'SM', 'T2')
THEN
CASE
WHEN time LIKE '201601%'
THEN
( (charge / POWER (10, decimals)) * 1.27131)
WHEN time LIKE '201602%'
THEN
( (charge / POWER (10, decimals)) * 1.27609)
WHEN time LIKE '201603%'
THEN
( (charge / POWER (10, decimals)) * 1.263019)
WHEN time LIKE '201604%'
THEN
( (charge / POWER (10, decimals)) * 1.251591)
WHEN time LIKE '201605%'
THEN
( (charge / POWER (10, decimals)) * 1.248002)
WHEN time LIKE '201606%'
THEN
( (charge / POWER (10, decimals)) * 1.252972)
WHEN time LIKE '201607%'
THEN
( (charge / POWER (10, decimals)) * 1.248432)
WHEN time LIKE '201608%'
THEN
( (charge / POWER (10, decimals)) * 1.25790)
WHEN time LIKE '201609%'
THEN
( (charge / POWER (10, decimals)) * 1.240378)
ELSE
0
END
ELSE
0
END)
OVER ()
AS charge
FROM ch
WHERE TYPE = 'MO'
AND pl IN ('IQ', 'SM', 'T2')
AND time BETWEEN '20160101000000' AND '20160930235959'
Второй запрос:
/* Formatted on 10.7.2016 1:36:11 (QP5 v5.163.1008.3004) */
SELECT DISTINCT
pl,
SUM (
CASE
WHEN pl IN ('AT', 'VV', 'CM')
THEN
CASE
WHEN time LIKE '201601%'
THEN
( (charge / POWER (10, decimals)) * 1.27131)
WHEN time LIKE '201602%'
THEN
( (charge / POWER (10, decimals)) * 1.27609)
WHEN time LIKE '201603%'
THEN
( (charge / POWER (10, decimals)) * 1.263019)
WHEN time LIKE '201604%'
THEN
( (charge / POWER (10, decimals)) * 1.251591)
WHEN time LIKE '201605%'
THEN
( (charge / POWER (10, decimals)) * 1.248002)
WHEN time LIKE '201606%'
THEN
( (charge / POWER (10, decimals)) * 1.252972)
WHEN time LIKE '201607%'
THEN
( (charge / POWER (10, decimals)) * 1.248432)
WHEN time LIKE '201608%'
THEN
( (charge / POWER (10, decimals)) * 1.25790)
WHEN time LIKE '201609%'
THEN
( (charge / POWER (10, decimals)) * 1.240378)
ELSE
0
END
ELSE
0
END)
OVER ()
AS charge
FROM ch
WHERE TYPE = 'MO'
AND pl IN ('AT', 'VV', 'CM')
AND time BETWEEN '20160101000000' AND '20160930235959'
Заранее спасибо за помощь
Комментарии:
1. Я удалил несовместимые теги базы данных. Пожалуйста, пометьте свой вопрос базой данных, которую вы фактически используете.
2. Есть ли какая-то особая причина использовать текстовый столбец для хранения данных {дата, время, временная метка} и их вызова
time
?
Ответ №1:
Кажется, вы хотите union all
:
with q1 as (
<first query here>
),
q2 as (
<second query here>
)
select q1.*
from q1
union all
select q2.*
from q2;
Комментарии:
1. Необходим ли CTE? Табличные значения могут быть встроены в виде подзапросов.
2. @Dai . , , CTE не требуется. Вместо этого можно использовать подзапросы.
Ответ №2:
Вы и вставляете UNION между 2 запросами, чтобы объединить их. Чтобы помочь вам с оптимизацией, мне нужно больше информации, например, структура таблицы, индексы … и т.д.
Ответ №3:
если ваш запрос имеет одинаковые имена полей в инструкции select, вы можете использовать «ОБЪЕДИНЕНИЕ». простой, например, является,
select id,name from table1 where condition
Union
select id,name from table2 where condition
это даст вам результат объединения обоих запросов.
Ответ №4:
Как уже упоминалось, странно, что вы, похоже, храните свои datetimes в виде строк. Но в любом случае:
Ваши запросы выбирают один и тот же тип и временной диапазон из таблицы, только один рассматривает один набор PLS, а другой — другой. Они даже используют одни и те же формулы в вашем предложении select . Так что это можно легко объединить
with factors as
(
select '201601%' as pattern, 1.27131 as factor
union all
select '201602%' as pattern, 1.27609 as factor
union all
select '201603%' as pattern, 1.263019 as factor
union all
select '201604%' as pattern, 1.251591 as factor
union all
select '201605%' as pattern, 1.248002 as factor
union all
select '201606%' as pattern, 1.252972 as factor
union all
select '201607%' as pattern, 1.248432 as factor
union all
select '201608%' as pattern, 1.25790 as factor
union all
select '201609%' as pattern, 1.240378 as factor
)
select pl, sum(charge) over
(partition by case when pl in ('IQ', 'SM', 'T2') then 1 else 2 end) as charge
from
(
select
pl,
sum(case when f.factor is null then 0
else ch.charge / power(10, ch.decimals) * f.factor end) as charge
from ch
left join factors f on ch.time like f.pattern
where type = 'MO'
and time BETWEEN '20160101000000' AND '20160930235959'
and pl in ('IQ', 'SM', 'T2', 'AT', 'VV', 'CM')
group by pl
) pls;
Вы даже можете сделать это без подзапроса. Выберите то, что вы считаете более удобным для чтения.
select
pl,
sum
(
sum(case when f.factor is null then 0
else ch.charge / power(10, ch.decimals) * f.factor end)
) over (partition by case when pl in ('IQ', 'SM', 'T2') then 1 else 2 end) as charge
from ch
left join factors f on ch.time like f.pattern
where type = 'MO'
and time BETWEEN '20160101000000' AND '20160930235959'
and pl in ('IQ', 'SM', 'T2', 'AT', 'VV', 'CM')
group by pl;
Возможно, вы захотите создать таблицу для факторов, чтобы избавиться от предложения with .