Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions labs/lab4.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
--Лабораторная работа 4.
--Для выполнения данной лабораторной работы необходимо установить подключение к БД dbSQL
--ВНИМАНИЕ: Вычисляемые столбцы должны иметь соответствующие наименования.
--Фильтрация должна выполняться на исходных столбцах (не на вычисляемых).
--Задание 1. Запросы с группировкой
--1. Выведите номер заказа и количество в нем продуктов со скидкой (используйте filter).
select o.orderid, count(d.productid) filter (where discount>0)
from "Sales"."Orders" as o
join "Sales"."OrderDetails" as d on o.orderid=d.orderid
group by o.orderid;
--2. Сформируйте выборку следующего вида:
select companyname, categoryname, count(p.productid) as count_products, avg(p.unitprice::numeric)::money, max(p.unitprice),min(p.unitprice)
from "Production"."Suppliers" as s
left join "Production"."Products" as p on s.supplierid = p.supplierid
join "Production"."Categories" as cat on p.categoryid = cat.categoryid
group by companyname, categoryname
having count(p.productid)>2;
--Выборка должна содержать информацию о поставщиках, которые поставляют более 2-х продуктов в каждой категории, а также максимальную, минимальную и среднюю цену поставляемых ими продуктов
--3. Сформируйте выборку следующего вида:
select split_part(companyname, ' ', 2), extract (YEAR from o.orderdate),count(distinct o.orderid), sum(d.unitprice * d.qty),count(distinct d.productid), count(d.unitprice) filter (where discount>0)
from "Sales"."Customers" as c
join "Sales"."Orders" as o on c.custid=o.custid
join "Sales"."OrderDetails" as d on o.orderid=d.orderid
where o.orderdate between '20060101'::date and '20061231'::date
group by c.custid, EXTRACT(YEAR FROM o.orderdate)
order by sum(d.unitprice * d.qty ) desc limit 5;
--PS: в задании указано учитывать скидку, в примере она не учитывается - сделал как в примере.
--Выборка должна содержать информацию о 5 самых выгодных заказчиках, с точки зрения суммарной стоимости (с учетом скидки) сделанных ими заказов в 2006.
--4. Выведите количество заказов в разрезе стран и в разрезе городов. Представьте два варианта:
--a. Первый вариант решения должен содержать количество заказов только по странам и только по городам,
--а также общее количество заказов
select shipcountry,shipcity, count(distinct orderid)
from "Sales"."Orders" as o
group by rollup(shipcountry, shipcity)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4.a. 0
Не выводится количество заказов по городам.

--b. Второй вариант – все возможные итоги (итог по стране, итог по городу, итог по стране и городу, общий итог).
select shipcountry,shipcity, count(distinct orderid)
from "Sales"."Orders" as o
group by cube(shipcountry, shipcity);
--* Используйте соответствующее расширение GROUP BY (GROUPING SETS, CUBE, ROLLUP)
--5. Сформируйте выборку следующего вида:
-- select split_part(companyname, ' ', 2), extract (YEAR from o.orderdate),count(distinct o.orderid), sum(d.unitprice * d.qty),count(distinct d.productid), count(d.unitprice) filter (where discount>0)
select split_part(companyname, ' ', 2), concat(c.country,', ',city) as ad, concat(c.country,', ',city) as shipad, sum(d.unitprice * d.qty*(1-d.discount))
from "Sales"."Customers" as c
join "Sales"."Orders" as o on c.custid=o.custid
join "Sales"."OrderDetails" as d on o.orderid=d.orderid
where o.orderdate between '20070301'::date and '20070630'::date and country = shipcountry and city=shipcity and country in ('Brazil','Canada')
group by c.companyname,
c.country,
c.city,
o.shipcountry,
o.shipcity
order by sum(d.unitprice * d.qty*(1-d.discount));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 0
    Неверно вычисляется shipad
    Неверная конечная дата периода

--Выборка должна содержать информацию о Заказчиках из Бразилии и Канады, которые сделали заказы весной 2007 года, при этом адрес доставки должен совпадать с адресом Заказчика (под адресом подразумевается страна и город).
--Столбец «Сумма заказов с учетом скидки» должен содержать общую стоимость заказов конкретного заказчика за указанный период
--Задание 2. Использование оконных функций
--1. Сформируйте выборку, следующего вида:
--
--Выборка должна выводить данные о заказах оформленных в сентябре 2006 года. Детали каждого заказа должны
--быть проранжированы в соответствие с их стоимостью.
select split_part(companyname, ' ', 2),o.orderid, d.productid, d.unitprice, d.qty,
(d.unitprice * d.qty * (1 - d.discount))::money as "Line Total",
sum(d.unitprice * d.qty * (1 - d.discount)) over(partition by o.orderid),
DENSE_RANK() OVER (PARTITION BY o.orderid ORDER BY d.unitprice * d.qty * (1 - d.discount) DESC) as "Line Rank"
from "Sales"."Customers" as c
join "Sales"."Orders" as o on c.custid=o.custid
join "Sales"."OrderDetails" as d on o.orderid=d.orderid
WHERE o.orderdate BETWEEN '2006-09-01'::date AND '2006-09-30'::date
order by o.orderid,c.companyname;
--2. Выведите список заказчиков, проранжировав их в пределах каждой страны отдельно в порядке убывания общей стоимости сделанных заказчиком заказов.
--Результирующая выборка должна содержать только строки со значением ранга не более 2
select *
from (select c.custid, companyname,c.country,
sum(d.unitprice * d.qty * (1 - d.discount))
, DENSE_RANK() OVER (PARTITION BY c.country ORDER BY sum(d.unitprice * d.qty * (1 - d.discount)) desc)
from "Sales"."Customers" as c
join "Sales"."Orders" as o on c.custid=o.custid
join "Sales"."OrderDetails" as d on o.orderid=d.orderid
group by c.custid
order by c.country,dense_rank)
where dense_rank<=2;
--3. Выведите для каждого продукта его название, цену по каталогу, количество заказов, в
-- которых данный продукт встречается, и ранг, в соответствии с частотой его присутствия в заказах
select
p.productname,
p.unitprice,
count(d.orderid) as qwt,
dense_rank() over( order by count(orderid) desc, p.productname asc)
from "Production"."Products" as p
join "Sales"."OrderDetails" as d on p.productid = d.productid
group by p.productname,p.unitprice;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2.3. Запрос не выводит товары, которые не входят ни в один заказ.

--4. Выведите одним запросом: номер заказчика, номер заказа, дату заказа, стоимость заказа,
--стоимость заказа за предыдущую дату по данному заказчику, разницу между стоимостью текущего заказа и предыдущего.
-- Null значения должны быть заменены 0.
--При расчете стоимости заказа необходимо учитывать скидку
select
c.custid,
o.orderid,
o.orderdate,
sum(d.unitprice * d.qty * (1 - d.discount))
, (lag(sum(d.unitprice * d.qty * (1 - d.discount))::numeric,1,0) over(order by c.custid, o.orderid, o.orderdate))::money
, sum(d.unitprice * d.qty * (1 - d.discount))-(lag(sum(d.unitprice * d.qty * (1 - d.discount))::numeric,1,0) over(order by c.custid, o.orderid, o.orderdate))::money
from "Sales"."Customers" as c
join "Sales"."Orders" as o on c.custid=o.custid
join "Sales"."OrderDetails" as d on o.orderid=d.orderid
group by c.custid,o.orderid;
--5. Выведите для всех заказов номер заказчика, номер заказа, дату заказа, объем заказа, процентную долю от общей
--стоимости всех заказов данного заказчика, нарастающий итог по заказам каждого заказчика.
select
c.custid,
o.orderid,
o.orderdate,
sum(d.unitprice * d.qty * (1 - d.discount)),
sum(d.unitprice * d.qty * (1 - d.discount))/sum(sum(d.unitprice * d.qty * (1 - d.discount))) over (partition by c.custid)*100,
sum(sum(d.unitprice * d.qty * (1 - d.discount))) over (partition by c.custid order by o.orderid)
from "Sales"."Customers" as c
join "Sales"."Orders" as o on c.custid=o.custid
join "Sales"."OrderDetails" as d on o.orderid=d.orderid
group by c.custid,o.orderid;
--6. Выведите для всех заказов, сделанных в 2007 году, название месяца, общий объем заказов в этом месяце, средний объем за 3 месяца (2 предыдущих и текущий) и нарастающий итого по месяцам. Воспользуйтесь представлением public."OrderValues"
SELECT
TO_CHAR(orderdate, 'Month') as monthname,
sum("OrderTotal") as order_count,
AVG(sum("OrderTotal")) OVER (
ORDER BY EXTRACT(MONTH FROM orderdate)
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) as avg_last_3_months,
sum(sum("OrderTotal")) OVER (
ORDER BY EXTRACT(MONTH FROM orderdate))
FROM public."OrderValues" as o
WHERE orderdate BETWEEN '2007-01-01'::date AND '2007-12-31'::date
GROUP BY TO_CHAR(orderdate, 'Month'), EXTRACT(MONTH FROM orderdate)
ORDER BY EXTRACT(MONTH FROM orderdate);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2.6. Не ошибка, а замечание: правильнее создать алиас для EXTRACT(MONTH FROM orderdate) и не вычислять каждый раз, а сортировать по алиасу.

--7. Выведите выборку, содержащую ФИО сотрудника магазина, год и месяц, когда он оформлял заказы, стоимость оформленных в конкретном месяце заказов, стоимость оформленных в конкретном году заказов, нарастающий итог по месяцам в каждом году для каждого сотрудника и Общий итог по всем заказам оформленным конкретным сотрудником.
select
concat(lastname,' ',firstname),
extract(year from orderdate),
extract(month from orderdate),
sum("OrderTotal")::money,
sum(sum("OrderTotal")) over(partition by concat(lastname,' ',firstname),extract(year from orderdate)),
sum(sum("OrderTotal")) over(partition by concat(lastname,' ',firstname),
extract(year from orderdate) order by concat(lastname,' ',firstname),extract(year from orderdate),extract(month from orderdate)),
sum(sum("OrderTotal")) over(partition by concat(lastname,' ',firstname))
from "HR"."Employees" as e
join public."OrderValues" as o on e.empid = o.empid
group by concat(lastname,' ',firstname),
extract(year from orderdate),
extract(month from orderdate)