#sql #oracle #group-by #having
#sql #Oracle #группировать по #имея
Вопрос:
У меня есть таблица, подобная:
SELECT
s.date,
s.orderid,
s.num1,
s.num2,
s.sales,
s.price
FROM sales AS s
В результате
date | orderid | num1 | num 1 | sales | price
2020-11-01 | 1 | a | aa | 1 | 10
2020-11-01 | 8 | k | kk | 1 | 10
2020-11-02 | 1 | a | aa | -1 | 10
2020-11-01 | 2 | b | bb | 2 | 8
2020-11-01 | 3 | c | cc | 1 | 10
2020-11-01 | 3 | c | cc | 2 | 9
2020-11-04 | 18 | u | uu | 5 | 2
«orderid» и «num1» должны появиться только один раз, в противном случае это возврат (вторая запись имеет значение «продажи» -1, что отрицает предыдущие продажи.
Итак, мне нужно полностью удалить эти записи (не сохраняя строку). В противном случае «orderid» не имеет никакого значения и не нужен.
Я хочу сгруппировать по «дате», «num1» и «num2», суммируя все продажи и получая среднюю цену при удалении идентификаторов заказов num1, которые появляются более одного раза вместе.
Конечный результат должен быть:
date | orderid | num1 | num 1 | sales | price
2020-11-01 | 8 | k | kk | 1 | 10
2020-11-01 | 2 | b | bb | 2 | 8
2020-11-01 | 3 | c | cc | 3 | 9.5
2020-11-04 | 18 | u | uu | 5 | 2
Как я могу сделать это с помощью Groupby? Пока у меня есть это:
SELECT
s.date,
s.num1,
s.num2,
SUM(s.sales),
AVG(s.price)
FROM sales AS s
GROUP BY s.date, s.num1, s.num2
Ответ №1:
Вы можете использовать оконные функции. На основе вашего описания (удаление заказов, которые появляются более одного раза), вы можете использовать count(*)
:
select s.date, s.num1, s.num2, SUM(s.sales), AVG(s.price)
from (select s.*, count(*) over (partition by orderid, num1) as cnt
from sales s
) s
where cnt = 1
group by s.date, s.num1, s.num2;
Я подозреваю, что вы действительно хотите row_number()
, поэтому сохраните одну из повторяющихся строк.
Комментарии:
1. Нет, мне не нужно сохранять строку, возвраты должны быть полностью отфильтрованы.
2. @Vega . . . Так что мое подозрение неверно, но ответ правильный.
Ответ №2:
Вы можете использовать group by
и having
следующим образом:
SELECT max(s.date) as date,
S.orderid,
s.num1,
s.num2,
SUM(s.sales),
AVG(s.price)
FROM sales AS s
GROUP BY s.orderid, s.num1, s.num2
Having sum(sales) > 0;
Ответ №3:
Вопрос:
Это журнал транзакций, в котором у вас есть OrderID 1 с записями продаж 10, 5, -1, 7, 8, что должно привести к значению 15? 10 и 5 отрицаются значением -1. Если это так, вам нужно выполнить запрос, который a) находит все строки после последнего -1 для этого OrderID и суммирует значения продаж.
Примером этого являются значения продаж для одного и того же идентификатора заказа 5, 6, -1, 7, 9, -1, 10, 2 который должен использовать только 10 и 2 для окончательной суммы
Что-то вроде
Запрос 1 — найдите максимальное значение (дата) для каждого идентификатора заказа, где сумма продаж равна -1 Запрос 2 — Используйте запрос 1, чтобы получить все транзакции для каждого идентификатора заказа, где дата> дата в запросе 1
С ПОМОЩЬЮ (определите запрос 1 здесь)
ВЫБЕРИТЕ s.OrderID, Sum(s.sales) как TotalSales, Avg(s.Price) как AveragePrice
ИЗ
ЛЕВОГО ВНЕШНЕГО СОЕДИНЕНИЯ sales (запрос 1) q1 ДЛЯ q1.OrderID
, ГДЕ (q1.Date равно нулю) ИЛИ (s.Date> q1.Дата)
ГРУППИРОВАТЬ ПО s.OrderID
Комментарии:
1. Это журнал продаж в базе данных Oracle. Каждая продажа регистрируется в строке, затем, если клиент возвращает товар, создается другая запись с тем же orderid и num1, но с отрицательным количеством, так что продажа возврат = продажа 0. Но мне нужно удалить их все вместе для моего варианта использования.