I have a sp as following to get a list of areacode(phone) and sales amount on a selected percentile. For example at 0.5. However, I don't only want to see the data at 0.5,I also want to see the data above 0.5(the selected parameter).How can I do with sql server coding?
CREATE PROCEDURE USP_Percentile1 #per real
AS
SELECT c.[area code],PERCENTILE_DISC(#per) WITHIN GROUP (ORDER BY SalesAmount) OVER (PARTITION BY [area code]) AS percentileamount
from (select SUBSTRING(s.phone,2,3) as [area code],sum(b.Salesamount) as SalesAmount from Orders a
join (select OrderID, sum(UnitPrice * Quantity * (1-Discount) ) as Salesamount from [Order Details] group by OrderID) as b
on a.OrderID = b.OrderID
join Shippers s
on a.ShipVia=s.ShipperID
group by s.Phone) c
exec SP_1 0.5
You can use the PERCENT_RANK function for this. Place it inside the subquery and filter it afterwards.
You should make good use of whitespace and formatting, it's free.
Also, see Bad Habits to Kick : Using table aliases like (a, b, c) or (t1, t2, t3)
CREATE PROCEDURE USP_Percentile1 #per real
AS
SELECT
o.[area code],
percentileamount
from (
select
SUBSTRING(s.phone, 2, 3) as [area code],
sum(od.Salesamount) as SalesAmount,
PERCENTILE_DISC(#per) WITHIN GROUP (ORDER BY sum(od.Salesamount)) OVER (PARTITION BY [area code]) AS percentileamount,
PERCENT_RANK() OVER (PARTITION BY [area code] ORDER BY sum(od.Salesamount)) AS percentile
from Orders o
join (
select
OrderID,
sum(UnitPrice * Quantity * (1-Discount) ) as Salesamount
from [Order Details]
group by OrderID
) as od on o.OrderID = od.OrderID
join Shippers s on o.ShipVia = s.ShipperID
group by s.Phone
) o
where
o.percentile >= #per;
Related
Write an SQL command that retrieves last name and first name of all customers and the order numbers of orders they have placed…
CustDetails TABLE: http://prntscr.com/msicdp
OrderDetails TABLE: http://prntscr.com/msichp
I am trying to display list of all users from CustDetails (table), with an additional column, "TotalOrders", that counts how many orders each user have from OrderDetails (table) with COUNT(*), but it seems like I have no idea what am I doing.
I've tried LEFT JOIN paired with COUNT(*) AS [Total Orders] and I am getting all kind of errors whatever I try
SELECT DISTINCT CustDetails.*, OrderDetails.CustRef,COUNT(*) AS [Order_number]
FROM CustDetails
LEFT JOIN OrderDetails ON CustDetails.CustRef = OrderDetails.CustRef
GROUP BY CustDetails.FName
--SELECT CustDetails.CustRef, count(*) AS NUM
-- FROM CustDetails GROUP BY CustRef
You can't put * with GROUP BY. If you are using GROUP BY, all non-aggregated columns should be present in your GROUP BY clause.
You need to write your query like the following.
select c.CustRef,
c.LName,
c.Fname,
sum(case when od.CustRef is null then 0 else 1 end) TotalOrders
from CustDetails c
left join OrderDetails od on od.CustRef =c.CustRef
group by c.CustRef ,c.LName, C.Fname
In case you need all the columns you can try like the following without GROUP BY.
select *,
(select count(*) from OrderDetails od where od.CustRef =c.CustRef) TotalOrders
from CustDetails c
Another way of doing it using PARTITION BY
select * from
(
select c.*,
sum(case when od.CustRef is null then 0 else 1 end) over(partition by c.CustRef) as TotalOrders,
row_number() over (partition by c.CustRef order by (select 1)) rn
from CustDetails c
left join OrderDetails od on od.CustRef =c.CustRef
) t
where rn=1
I need a query for [Contribution]. I used this query:
with ttt as
(
select
(DYG.U_StyleId)[DYG Style]
,Max(O1.CardCode) [Party Group Code],
MAX(O1.CardName) [Party Group Name]
,MAX(OR1.DocDate) [Date]
,sum(CONVERT(NUMERIC(15,2),(RDR1.PriceBefDi*RDR1.Quantity))) [JobAmount]
,CONVERT(NUMERIC(15,2),SUM(RDR1.Quantity)) [Mtr]
,CONVERT(NUMERIC(15,2),SUM(RDR1.U_Pcs))[Pcs]
,(select sum(RDR1.PriceBefDi*RDR1.Quantity) from RDR1) tqty
from
ORDR OR1
left join RDR1 on RDR1.DocEntry = OR1.DocEntry
left join OITM on RDR1.ItemCode = oitm.ItemCode
LEFT JOIN OCRD ON OCRD.CardCode = OR1.CardCode
LEFT JOIN OCRG ON OCRG.GroupCode = OCRD.GroupCode
LEFT JOIN OCRD O1 ON O1.U_BCode = OCRD.U_GrpCod
LEFT JOIN
( SELECT U_StyleId FROM RDR1 WHERE U_StyleId in
('BLOOM','BLOOMING','DYD','DYD-R','DYED','Ex.CLR.','RAINBOW'))
DYG ON DYG.U_StyleId = RDR1.U_StyleId
group by
DYG.U_StyleId
)
select
Style, [Party Group Code],
[Party Group Name], JobAmount,
(sum(JobAmount) / tqty * 100) [Contribution],
[Date], [Pcs]
from
ttt
group by
Style
I need Sum of last jobamount to divide it with above tqty.
But it shows this error.
'Column 'ttt.Party Group Code' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.'
Please help me with the query to get right [Contribution] amount.
Try this:
select Style,[Party Group Code],[Party Group Name],JobAmount,[Date],[Pcs],
100.0 * (sum(JobAmount) OVER (PARTITION BY Style))/tqty [Contribution]
from ttt;
This is my first time around here :p
I have SQL Server practice.
Based on the country where Northwind customers reside, show the sum of the 5 highest purchase orders by country. The results should be presented in two columns: country, amount
I tried:
SELECT
vt.ShipCountry, vt.suma
FROM
(SELECT
o.ShipCountry,
SUM( UnitPrice * Quantity * (1-discount)) as suma,
RANK() OVER (PARTITION BY SUM(UnitPrice * Quantity * (1-discount)) ORDER BY shipCountry DESC) AS Rank
FROM
orders o
JOIN
[Order Details] od ON o.OrderID = od.OrderID
GROUP BY
o.ShipCountry) as vt
WHERE
Rank <= 5
GROUP BY
vt.ShipCOUNTRY, vt.suma
but, it retrieves me the sum of all orders per country, only want the top 5 per country
Here's another one, same issue.
SELECT
ShipCountry, rk, amount
FROM
(SELECT
o.ShipCountry,
SUM(UnitPrice * Quantity * (1-discount)) amount,
DENSE_RANK() OVER(PARTITION BY o.ShipCountry ORDER BY SUM(UnitPrice * Quantity * (1-discount)) DESC) AS rk
FROM
Orders o
JOIN
[Order Details] od ON o.OrderID = od.OrderID
GROUP BY
o.shipCountry) AS L
WHERE
rk <= 5;
The two queries have the same behaviour
Try this:
-- first, sum up the total amount of each order
;WITH OrderDetails AS
(
SELECT
o.OrderID,
TotalOrderAmount = SUM(UnitPrice * Quantity * (1 - discount))
FROM
orders o
INNER JOIN
[Order Details] od ON o.OrderID = od.OrderID
GROUP BY
o.OrderID
),
-- secondly, join the "ShipCountry" to the order totals,
-- and define a ROW_NUMBER() for each country, based on
-- total order amount
OrderPerCountry AS
(
SELECT
o.ShipCountry,
od.TotalOrderAmount,
RowNum = ROW_NUMBER() OVER(PARTITION BY o.ShipCountry ORDER BY od.TotalOrderAmount DESC)
FROM
OrderDetails od
INNER JOIN
dbo.Orders o ON o.OrderID = od.OrderID
)
SELECT *
FROM OrderPerCountry
WHERE RowNum <= 5
This should do the trick for you - I hope!
I'm trying to do this task:
Find total amount of all orders for each customer, sort customers by
the value from maximum amount to minimum and show customers from 40 to
50 position in the result. Only one query.
I'm training on Northwind sample database. My query:
;WITH MyCte AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY SUM(OD.UnitPrice*OD.Quantity*(1-OD.Discount)) DESC) Number
, O.CustomerID
, SUM(OD.UnitPrice*OD.Quantity*(1-OD.Discount)) TotalAmount
FROM [Order Details] OD
RIGHT JOIN Orders O ON OD.OrderID = O.OrderID
GROUP BY CustomerID
ORDER BY TotalAmount DESC
)
SELECT
Number
, CustomerID
, TotalAmount
FROM MyCte
WHERE Number BETWEEN 40 AND 50
But this doesn't work. May someone help me to put "Where" correctly to this query?
;WITH MyCte AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY SUM(OD.UnitPrice*OD.Quantity*(1-OD.Discount)) DESC) Number
, O.CustomerID
, SUM(OD.UnitPrice*OD.Quantity*(1-OD.Discount)) TotalAmount
FROM [Order Details] OD
RIGHT JOIN Orders O ON OD.OrderID = O.OrderID
GROUP BY CustomerID
)
SELECT
Number
, CustomerID
, TotalAmount
FROM MyCte
WHERE Number >= 40 and Number <= 50
Main trouble was in Order By in MyCTE table. This query will work.
I have a request I wasn't sure to handle. I was thinking of using PIVOT, but I wasn't sure if that would be the way to go.
I have the following Data:
EmployeeA, DepartmentB, 1/10/2010
EmployeeA, DepartmentA, 1/1/2000
EmployeeB, DepartmentC, 1/3/2011
They want output for only the employees that have been in different departments. Something that looks like this (order is important due to the dates):
EmployeeA, DepartmentA, DepartmentB
Any help is appreciated. For some reason, my mind isn't finding a good solution.
You can do this by doing a self JOIN on the table and then using a PIVOT to get the data in the format that you want:
SELECT *
FROM
(
SELECT t1.emp, t1.dept, t1.dt
FROM test t1
INNER JOIN test t2
ON t1.emp = t2.emp
AND t1.dept != t2.dept
) x
PIVOT
(
min(dt)
for dept in ([A], [B], [C], [D], [E])
) p
See SQL Fiddle with Demo
If you remove the JOIN you will get all records, but you stated you only want the records that have been in more than one department.
Here's the answer I got which I got largely based on your work. Pivot doesn't work because I don't know the categories (in this case Department) ahead of time and I can only have two of them.
Maybe there's an easier way. I didn't use a CTE, because I believe this should work for Sybase as well which I don't think supports that.
select Meta1.[Employee ID],
Meta1.Department as PreviousDepartment,
Meta2.Department as CurrentDepartment
from
(
SELECT t1.[First Name], t1.[Last Name],
t1.[Employee ID], t1.Department, t1.[Hire Date],
ROW_NUMBER() over(PARTITION by t1.[EMPLOYEE ID] order by t1.[Hire Date]) as RowNum
FROM EMPLOYEE t1
INNER JOIN EMPLOYEE t2
ON t1.[Employee ID] = t2.[Employee ID]
AND t1.Department != t2.Department
) Meta1
inner join
(
SELECT t1.[Employee ID], t1.Department, t1.[Hire Date],
ROW_NUMBER() over(PARTITION by t1.[EMPLOYEE ID] order by t1.[Hire Date]) as RowNum
FROM EMPLOYEE t1
INNER JOIN EMPLOYEE t2
ON t1.[Employee ID] = t2.[Employee ID]
AND t1.Department != t2.Department
) Meta2
on Meta1.[Employee ID]=Meta2.[Employee ID]
where Meta1.RowNum=1
and Meta2.RowNum=2