From 562736c4e74dbb7a493ec2f7b07c617691b381a4 Mon Sep 17 00:00:00 2001 From: plidan123 Date: Wed, 8 Oct 2025 14:00:49 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BB=D0=B0=D0=B1=D0=BE=D1=80=D0=B0=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=BD=D0=B0=D1=8F=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=204?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- labs/lab4.sql | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 labs/lab4.sql diff --git a/labs/lab4.sql b/labs/lab4.sql new file mode 100644 index 0000000..2c6b4a9 --- /dev/null +++ b/labs/lab4.sql @@ -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) +--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)); +--Выборка должна содержать информацию о Заказчиках из Бразилии и Канады, которые сделали заказы весной 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; +--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); +--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) +