TSQL Lab 09 習題

LAB 09
Exercise 1

---------------------------------------------------------------------
-- Task 2
-- 
-- Write a SELECT statement that will return groups of customers that made a purchase.
-- The SELECT clause should include the custid column from the Sales.Orders table 
-- and the contactname column from the Sales.Customers table. 
-- Group by both columns and filter only the orders from the sales employee 
-- whose empid equals five.
---------------------------------------------------------------------

寫法1
select c.custid,c.contactname
from Sales.Customers c
inner join Sales.Orders o
on c.custid = o.custid
where o.empid = 5
group by c.custid,c.contactname


寫法2
select distinct(o.custid), c.contactname,o.empid
from Sales.Orders o
inner join Sales.Customers c
on o.custid = c.custid
where o.empid = 5
order by o.custid asc

---------------------------------------------------------------------
-- Task 3
-- 
-- Copy the T-SQL statement in task 2 and modify it to include the city column 
-- from the Sales.Customers table in the SELECT clause. 
--
-- Execute the query. You will get an error. What is the error message? Why?
--
-- Correct the query so that it will execute properly.
---------------------------------------------------------------------

select c.custid,c.contactname,c.city
from Sales.Customers c
inner join Sales.Orders o
on c.custid = o.custid
where o.empid = 5
group by c.custid,c.contactname

-- error

select c.custid,c.contactname,c.city
from Sales.Customers c
inner join Sales.Orders o
on c.custid = o.custid
where o.empid = 5
group by c.custid,c.contactname,c.city
-- correct

因為多增加的欄位沒有包含在group by 群組裡

---------------------------------------------------------------------
-- Task 4
-- 
-- Write a SELECT statement that will return groups of rows based on the custid column 
-- and a calculated column orderyear representing the order year based on the orderdate column
-- from the Sales.Orders table. 
-- Filter the results to include only the orders from the sales employee whose empid 
-- equal five.
---------------------------------------------------------------------

寫法1
SELECT
custid, YEAR(orderdate) AS orderyear
FROM Sales.Orders
WHERE empid = 5
GROUP BY custid, YEAR(orderdate)
ORDER BY custid, orderyear;

寫法2
select distinct(custid),YEAR(orderdate) as orderyear,empid
from Sales.Orders
where empid = 5
order by orderyear asc,custid asc

---------------------------------------------------------------------
-- Task 5
-- 
-- Write a SELECT statement to retrieve groups of rows based on the categoryname column 
-- in the Production.Categories table. Filter the results to include only the 
-- product categories that were ordered in the year 2008.
---------------------------------------------------------------------

select
--distinct(p.productid),p.productname,
--o.orderdate,
c.categoryid,c.categoryname
from Production.Categories c
inner join Production.Products p
on c.categoryid = p.categoryid
inner join Sales.OrderDetails od
on p.productid = od.productid
inner join Sales.Orders o
on o.orderid = od.orderid
where YEAR(o.orderdate) = '2008'
group by c.categoryid,c.categoryname



Exercise 2

---------------------------------------------------------------------
-- Task 1
-- 
-- Write a SELECT statement to retrieve the orderid column from the Sales.Orders table
-- and the total sales amount per orderid. (Hint: Multiply the qty and unitprice columns
-- from the Sales.OrderDetails table.) Use the alias salesmount for the calculated column.
-- Sort the result by the total sales amount in descending order.
--------------------------------------------------------------------

select o.orderid, o.orderdate,SUM(od.qty*od.unitprice) as salesmount
from Sales.Orders o
inner join Sales.OrderDetails od
on o.orderid = od.orderid 
group by o.orderid,o.orderdate
order by salesmount desc


---------------------------------------------------------------------
-- Task 2
-- 
-- Copy the T-SQL statement in task 1 and modify it to include
-- the total number of order lines for each order and 
-- the average order line sales amount value within the order. 
-- Use the aliases nooforderlines and avgsalesamountperorderline, respectively.
--------------------------------------------------------------------

select 
o.orderid
,o.orderdate
,SUM(od.qty*od.unitprice) as salesmount
,COUNT(*) AS noofoderlines
,AVG(od.qty*od.unitprice) as avgsalesamountperorderline
from Sales.Orders o
inner join Sales.OrderDetails od
on o.orderid = od.orderid 
group by o.orderid,o.orderdate
ORDER BY salesmount DESC;



---------------------------------------------------------------------
-- Task 3
-- 
-- Write a select statement to retrieve the total sales amount for each month.
-- The SELECT clause should include a calculated column 
-- named yearmonthno (YYYYMM notation) based on the orderdate column in the Sales.Orders
-- table and a total sales amount (multiply the qty and unitprice columns from 
-- the Sales.OrderDetails table). Order the result by the yearmonthno calculated column.
-- Execute the written statement and compare the results that you got with the recommended result shown in the file 64 - Lab Exercise 2 - Task 3 Result.txt.
---------------------------------------------------------------------


select 
CONVERT(nvarchar(6), o.orderdate, 112) as yearmonthno
,SUM(od.qty*od.unitprice) as saleamountpermonth
from Sales.Orders o
inner join Sales.OrderDetails od
on o.orderid = od.orderid 
group by CONVERT(nvarchar(6), o.orderdate, 112)
ORDER BY yearmonthno ASC;



--------------------------------------------------------------------
-- Task 4
-- 
-- Write a select statement to retrieve all the customers 
-- (including those that did not place any orders) and their total sales amount,
--  maximum sales amount per order line, and number of order lines. 
--
-- The SELECT clause should include the custid and contactname columns from 
-- the Sales.Customers table and four calculated columns based on appropriate aggregate functions:
-- totalsalesamount, representing the total sales amount per order
--  maxsalesamountperorderline, representing the maximum sales amount per order line
--  numberofrows, representing the number of rows (use * in the COUNT function)
--  numberoforderlines, representing the number of order lines (use the orderid column in the COUNT function)
--
-- Order the result by the totalsalesamount column.
-- Notice that the custid 22 and 57 rows 
-- have a NULL in the columns with the SUM and MAX aggregate functions. 
-- What are their values in the COUNT columns? Why are they different?
---------------------------------------------------------------------

select 
c.custid
,c.contactname
,SUM(od.qty*od.unitprice) as totalsalesamount
,MAX(od.qty*od.unitprice) as maxsalesamountperorderline
,count(*) as numberofrows
,count(o.orderid) as numberoforderlines
from Sales.Customers c
left join Sales.Orders o
on o.custid = c.custid
left join Sales.OrderDetails od
on o.orderid = od.orderid
group by c.custid,c.contactname
order by c.custid asc

因 numberofrows 按照custid去計算因此有一筆
numberoforderlines 按照orderid去計算,顧客沒訂單,所以0筆




Exercise 3
---------------------------------------------------------------------
-- Task 1
-- 
-- A junior analyst prepared a T-SQL statement to retrieve the number of orders
-- and the number of customers for each order year. 
-- Observe the provided T-SQL statement and execute it:
--
-- Observe the result and notice that the number of orders is the same 
-- as the number of customers. Why?
--
-- Correct the T-SQL statement to show the correct number of customers 
-- that placed an order for each year.
---------------------------------------------------------------------

SELECT
YEAR(orderdate) AS orderyear, 
COUNT(orderid) AS nooforders, 
count(distinct(custid)) AS noofcustomers
FROM Sales.Orders 
GROUP BY YEAR(orderdate);

---------------------------------------------------------------------
-- Task 2
-- 
-- Write a SELECT statement to retrieve the number of customers based on the first letter
-- of the values in the contactname column from the Sales.Customers table. 
-- Add an additional column to show the total number of orders placed by each group of customers.
-- Use the aliases firstletter, noofcustomers and nooforders. 
-- Order the result by the firstletter column.
------------------------------------------------------------------

select 
SUBSTRING(c.contactname,1,1) as firstletter
,COUNT(distinct c.custid) as noofcustomers
,COUNT(o.orderid) as nooforders
from Sales.Customers c
left join Sales.Orders o
on c.custid = o.custid
group by SUBSTRING(c.contactname,1,1)
order by firstletter asc

---------------------------------------------------------------------
-- Task 3
-- 
-- Copy the T-SQL statement in exercise 1, task 4, 
-- and modify to include the following information about for each product category: 
-- total sales amount, number of orders, and average sales amount per order. 
-- Use the aliases totalsalesamount, nooforders, and avgsalesamountperorder, respectively.
---------------------------------------------------------------------

select 
c.categoryid
,c.categoryname
,SUM(od.unitprice*od.qty) as totalsalesamount
,COUNT(distinct od.orderid) as nooforders
,SUM(od.unitprice*od.qty)/COUNT(distinct od.orderid) as avgsalesamountperorder
from Production.Categories c
inner join Production.Products p
on c.categoryid = p.categoryid
inner join Sales.OrderDetails od
on p.productid = od.productid
inner join Sales.Orders o
on o.orderid = od.orderid
where YEAR(o.orderdate) = '2008'
group by c.categoryid,c.categoryname


Exercise 4

---------------------------------------------------------------------
-- Task 1
-- 
-- Write a SELECT statement to retrieve the top 10 customers by total sales amount 
-- that spent more than $10,000 in terms of sales amount. 
-- Display the custid column from the Orders table and a calculated column
-- that contains the total sales amount based on the qty and unitprice columns 
-- from the Sales.OrderDetails table. Use the alias totalsalesamount for the calculated column.
---------------------------------------------------------------------

select top 10 o.custid,SUM(od.unitprice*od.qty) as totalsalesamount
from Sales.Orders o
inner join Sales.OrderDetails od
on o.orderid = od.orderid
group by o.custid
having SUM(od.unitprice*od.qty) > 10000
order by totalsalesamount desc

---------------------------------------------------------------------
-- Task 2
-- 
-- Write a SELECT statement against the Sales.Orders and Sales.OrderDetails tables 
-- and display the empid column and a calculated column representing the total sales amount. 
-- Filter the result to group only the rows with an order year 2008.
---------------------------------------------------------------------

select o.orderid, o.empid, SUM(od.unitprice*od.qty) as totalsalesamount
from Sales.Orders o
inner join Sales.OrderDetails od
on o.orderid = od.orderid
where YEAR(o.orderdate) = 2008
group by o.orderid,o.empid

---------------------------------------------------------------------
-- Task 3
-- 
-- Copy the T-SQL statement in task 2 and modify it to apply an additional filter
-- to retrieve only the rows that have a sales amount higher than $10,000.
--
-- Execute the written statement and compare the results 
-- that you got with the recommended result shown in the file 84 - Lab Exercise 4 - Task 3_1 Result.txt.
-- Apply an additional filter to show only employees with empid equal number 3.
--
-- Execute the written statement and compare the results that you got with the recommended result
-- shown in the file 85 - Lab Exercise 4 - Task 3_2 Result.txt.
--
-- Did you apply the predicate logic in the WHERE or in the HAVING clause? 
-- Which do you think is better? Why?
---------------------------------------------------------------------

--Add having
select o.orderid, o.empid, SUM(od.unitprice*od.qty) as totalsalesamount
from Sales.Orders o
inner join Sales.OrderDetails od
on o.orderid = od.orderid
where YEAR(o.orderdate) = 2008
group by o.orderid,o.empid
having SUM(od.unitprice*od.qty) >= 10000


--Add predicate
select o.orderid, o.empid, SUM(od.unitprice*od.qty) as totalsalesamount
from Sales.Orders o
inner join Sales.OrderDetails od
on o.orderid = od.orderid
where YEAR(o.orderdate) = 2008 and o.empid = 3
group by o.orderid,o.empid
having SUM(od.unitprice*od.qty) >= 10000

--HAVING是給匯總函數條件使用,一般過濾條件還是用WHERE

---------------------------------------------------------------------
-- Task 4
-- 
-- Write a SELECT statement to retrieve all customers who placed more than 25 orders
-- and add information about the date of the last order and the total sales amount. 
-- Display the custid column from the Sales.Orders table and two calculated columns: 
-- lastorderdate based on the orderdate column and totalsalesamount based on 
-- the qty and unitprice columns in the Sales.OrderDetails table.
---------------------------------------------------------------------

select o.custid
,MAX(o.orderdate) as lastorderdate
,SUM(od.unitprice*od.qty) as totalsalesamount
-- ,COUNT(distinct o.orderid)
from Sales.Orders o
inner join Sales.OrderDetails od
on o.orderid = od.orderid
group by o.custid
having COUNT(distinct o.orderid) > 25

--串了OrderDetails後,Orderid會因每筆訂單不同商品數而重複所以需DISTINCT


留言

這個網誌中的熱門文章

TSQL Lab 06 習題

TSQL Lab 08 習題