Как написать оракул SQL-запрос, который включает в себя несколько вариантов выбора - PullRequest
0 голосов
/ 22 сентября 2019

У меня есть этот запрос, который дает мне название предмета, среднюю цену и количество для определенного года, как показано ниже.

name      Avg_price_2019    count
---------------------------------
X         23.9              234
Y         21.8               59

SQL:

SELECT 
    AVG(Amount) Avg_price_2019, name 
FROM
    (SELECT 
         name, SUM(price_amount) Amount, COUNT(*) 
     FROM 
         myTable
     WHERE
         (To_date("Activity Date", 'mm-dd-yyyy') >= TO_DATE('09/01/2019', 'mm/dd/yyyy'))
         AND (To_date("Activity Date", 'mm-dd-yyyy') <= TO_DATE('09/17/2019','mm/dd/yyyy')) 
     GROUP BY
         name)
GROUP BY
    name;

Iхочу, чтобы он возвращал больше лет, как показано ниже

name | Avg price 2018 | count | Avg price 2019 | count

Для результатов 2018 года мне нужен один и тот же запрос, просто меняющий год.

Как объединить эти два выбора в одном запроседля получения вышеуказанного результата?

Ответы [ 3 ]

1 голос
/ 22 сентября 2019

Кажется, вы хотите условную агрегацию.Ваш запрос, скорее всего, можно упростить следующим образом:

SELECT
    name 
    AVG(CASE WHEN EXTRACT(YEAR FROM Activity_Date) = 2019 THEN Amount END) avg_price_2019,
    SUM(CASE WHEN EXTRACT(YEAR FROM Activity_Date) = 2019 THEN 1 ELSE 0 END) count_2019,  
    AVG(CASE WHEN EXTRACT(YEAR FROM Activity_Date) = 2018 THEN Amount END) avg_price_2018,
    SUM(CASE WHEN EXTRACT(YEAR FROM Activity_Date) = 2018 THEN 1 ELSE 0 END) count_2018
FROM myTable 
GROUP BY name

Похоже, вы храните даты в виде строки в формате mm-dd-yyyy.Вы можете использовать SUBSTR() для извлечения части года, например:

SELECT
    name 
    AVG(CASE WHEN SUBSTR(Activity_Date, -4) = '2019' THEN Amount END) avg_price_2019,
    SUM(CASE WHEN SUBSTR(Activity_Date, -4) = '2019' THEN 1 ELSE 0 END) count_2019,  
    AVG(CASE WHEN SUBSTR(Activity_Date, -4) = '2018' THEN Amount END) avg_price_2018,
    SUM(CASE WHEN SUBSTR(Activity_Date, -4) = '2018' THEN 1 ELSE 0 END) count_2018
FROM myTable 
GROUP BY name

Наконец, если вы хотите выполнить фильтрацию по определенному периоду года (с 1 по 17 сентября), тогда выможно добавить предложение WHERE к запросу.Все еще предполагая, что даты хранятся в виде строк, это может быть:

WHERE SUBSTR(Activity_Date, 1, 5) BETWEEN '09-01' AND '09-17'
0 голосов
/ 22 сентября 2019

Это предложение where:

Create Table myTable 
(

    myTableID int,
    amount int,
    price_amount int,
    to_date DateTime,
    activity_date DateTime

)

Insert Into myTable (myTableID, amount, price_amount, activity_date) values (1, 1, 2, '1/1/2019')
Insert Into myTable (myTableID, amount, price_amount, activity_date) values (1, 1, 4, '1/1/2018')

select * from myTable

Select AVG(amount) as Avg_price_2019, 
   (SELECT SUM(price_amount) FROM myTable) as test from myTable
   where activity_date >= Convert(DateTime, '09/01/2019')
   and activity_date <= Convert(DateTime, '09/17/2019')
0 голосов
/ 22 сентября 2019

В этом случае я бы использовал «столбец поддельной карты»

select a.NAME, a.AVG. a.CNT, b.AVG, b.CNT from 
(
select '1' as MAP, NAME, AVG, CNT from ... your query [2018 table] ...
) a
left join
(
select '1' as MAP, NAME, AVG, CNT from ... your query [2019 table] ...
) b
on a.MAP = b.MAP

Я не тестировал код, но я пытаюсь сказать, что вы можете создать фиктивный столбец в каждой таблице, а затемоставьте их в этом столбце, чтобы получить их рядом.

Также для повышения производительности я бы порекомендовал использовать 'BETWEEN' при фильтрации Datetime Например: DATE BETWEEN date1 и date2

...