SQL divide the column values to equal groups with ntile - sql

I need to write sql query that divide the products to 3 equal groups by their price, (The cheapest products will be in the first group). For each group I have to present the price ranges it includes and the average units in stock.
I try to use ntile but I got stuck:
SELECT UnitPrice, NTILE(3) OVER (
ORDER BY UnitPrice ASC
) AS productGroup, UnitsInStock
FROM Products

You need to put a query on top of this one. Something like this:-
select productGroup, min(UnitPrice), max(UnitPrice), avg(UnitPrice)
from (
SELECT UnitPrice, NTILE(3) OVER (ORDER BY UnitPrice ASC) AS productGroup
, UnitsInStock
FROM Products
) t1
group by productGroup

Related

Get the date for each duplicated row in SQL Server

I've made a query to get how many products are sold more than one time and it worked.
Now I want to show the transaction date for each of these duplicated sales, but when I insert the date on the select it brings me a lot less rows: something is going wrong. The query without the date returns 9855 rows and with the date just 36 rows.
Here is the query I'm doing:
SELECT TransactionDate,
ProductName,
QtyOfSales = COUNT(*)
FROM product_sales
WHERE ProductID = 1 -- Product Sold ID
AND ProductName IS NOT NULL
GROUP BY ProductName,
TransactionDate
HAVING COUNT(*) > 1
Perhaps a subquery? Can you help in that regard?
You can use the corresponding COUNT window function, that will find the amount of transactions by partitioning on the "ProductName" as required:
WITH cte AS(
SELECT TransactionDate,
ProductName,
COUNT(*) OVER(PARTITION BY ProductName) AS QtyOfSales
FROM product_sales
WHERE ProductID = 1 -- Product Sold ID
AND ProductName IS NOT NULL
)
SELECT DISTINCT TransactionDate,
ProductName
FROM cte
WHERE QtyOfSales > 1

Retrieve top selling products

I would like to receive top 5 selling products in quantity in an order from NorthWind database.
The database has a bunch of tables like Order, OrderDetails, Customers, etc. I was suggested to use Orders Details table below:
Now, I tried the following:
WITH cte AS (
SELECT
OrderID,
Quantity,
ProductID,
ROW_NUMBER() OVER(PARTITION BY OrderID ORDER BY OrderID) as row_num
FROM [Order Details]
)
SELECT *
FROM cte
WHERE row_num IN (SELECT row_num FROM cte WHERE row_num <=10)
ORDER BY OrderID;
Thought this retrieves 10 rows now for each order, they are not ordered based on sold quantities and top sold products are not retrieved properly as for some orders the top sold was beyond the first top 10 rows based on row number I got with ROW_NUMBER() function in SQL.
Edit: For example, if I have 10 orders each with 20 products, then I want top 5 each each product, so the result table should have 50 rows total.
After your edits:
WITH cte AS (
SELECT
OrderID,
Quantity,
ProductID,
ROW_NUMBER() OVER(PARTITION BY OrderID ORDER BY Quantity DESC) as row_num
FROM [Order Details]
)
SELECT *
FROM cte
WHERE row_num <= 5
ORDER BY OrderID;
You should do a
SELECT DISTINCT productid FROM OrderDetails ORDER BY quantity GROUP BY productId LIMIT 5
At least this is the mysql syntax.

select top selling size by product group from table

I have table called Orders. There are three columns: CustomerID, ProductGroup, Size.
How can I get TOP selling size by ProductGroup from this table?
I can do it 1 by 1 with
SELECT TOP 1 Count(customerid) as customers, ProductGroup, Size
FROM Orders
WHERE ProductGroup = xxx
GROUP BY ProductGroup, Size
ORDER BY Count(customerid) DESC
However, I would like to get full list at once.
Not sure, but it may help you.
Declare #temp table(CustomerID int, ProductGroup varchar(10), Size int)
insert into #temp
Select 1,'ABC',15 union all
Select 2,'ABC',10 union all
Select 3,'XYZ',12 union all
Select 4,'ABC',15 union all
Select 3,'XYZ',12 union all
Select 3,'XYZ',12 union all
Select 3,'XYZ',15 union all
Select 3,'XYZ',11 union all
Select 3,'XYZ',12
Select * from (
Select RANK() Over(PARTITION BY ProductGroup order by customers desc) RankVal,customers,ProductGroup, Size
from (
SELECT Count(CustomerID) as customers, ProductGroup, Size
FROM #temp
GROUP BY ProductGroup, Size
) T
)T1
WHERE RankVal = 1
Please check following SELECT query with SQL Count using Partition By clause
;with cte as (
SELECT
Distinct ProductGroup, Size,
COUNT(*) OVER (Partition By ProductGroup, Size) cnt
FROM Customers
)
select
ProductGroup, Size, cnt
from (
select *,
rn = ROW_NUMBER() OVER (Partition By ProductGroup Order By cnt desc)
from cte
) t
where rn = 1
You want to have the top selling product for every ProductGroup. The way to achieve this, is to use a group by, e.g. via
SELECT ProductGroup, MAX(size)
FROM orders
GROUP BY ProductGroup
This way you get a result table with one column per ProductGroup and the maximum of the sizes by this product group.
You can use the aggregate function max() to select the highest size and group it according to ProductGroup.
SELECT COUNT(customerid) as customers, ProductGroup, MAX(Size) FROM
Orders WHERE Size IN (SELECT MAX(Size) FROM Orders) GROUP BY ProductGroup
ORDER BY customerid DESC;
Note that this query has not been tested yet and I wonder if why do you need to get the count of customerid if your selecting only the highest Size per ProductGroup.
You can try to use the MAX operator and put your SQL in a subquery, like this (not tested):
SELECT MAX(customers), ProductGroup, Size FROM Orders GROUP BY ProductGroup, Size HAVING MAX(customers) =
SELECT MAX(customers) AS myMax FROM (
SELECT Count(customerid) as customers, ProductGroup, Size
FROM Orders
GROUP BY ProductGroup, Size) AS O
GROUP BY ProductGroup, Size

SQL Query: SELECT MAX SUM quantity

How do i combine a SUM and MAX in a single query?
Lets say i have a orderrule:
ProductID \ Quantity
I Could say:
Select ProductID,SUM(Quantity) AS Sold
FROM Orderrule
GROUP BY ProductID
ORDER BY SUM(Quantity) Desc
However that would return all sales, and not just the most sold product (with quantity).
Try this
SELECT TOP(1)
*
FROM
(
Select
ProductID,
MAX(Quantity) As MaxQuantity,
SUM(Quantity) AS Sold
FROM Orderrule
GROUP BY ProductID
)AS X
ORDER BY Sold DESC
So there are two ways to do it - first to have a limit on the number of results, something likes:
select * from (your_select) where rownum = 1
the other one is to pick the one with the the highest value, which will require a subselect, something like:
having sum(quantity) =
(select max(sum_quan) from (select sum(Quantity) from orderrule group by Product_id))
SELECT TOP 1 ProductID, Sold FROM
(
SELECT ProductID, SUM(Quantity) AS Sold
FROM Orderrule
GROUP BY ProductID
) totals
ORDER BY Sold DESC

Dedupe records without DELETE

I need to bring back only one of the records from a duplicated row in SQL Server
I have data like this
-------------------------------------------
CustomerID, OrderID, ProductID, Title
-------------------------------------------
1,1001,131,orange
1,1002,131,orange
-------------------------------------------
These rows are shown as 2 items that have been ordered by the same person, really they are just two as the quantity chosen in the basket and 2 records.
My question is how can i retrieve only one of these rows?
Thanks
Maybe something like this:
First some test data:
DECLARE #tbl TABLE(CustomerID INT,OrderID INT,ProductID INT,Title VARCHAR(100))
INSERT INTO #tbl
VALUES
(1,1001,131,'orange'),
(1,1002,131,'orange')
Then the query
;WITH CTE AS
(
SELECT
ROW_NUMBER() OVER(PARTITION BY tbl.CustomerID,tbl.ProductID,tbl.Title
ORDER BY tbl.OrderID) AS RowNbr,
tbl.CustomerID,
tbl.OrderID,
tbl.ProductID,
tbl.Title
FROM
#tbl AS tbl
)
SELECT
*
FROM
CTE
WHERE
CTE.RowNbr=1
This way you can get, not only one of both rows, but also the quantity ordered
SELECT
CustomerID, ProductID, Title, max(OrderID) as orderID, COUNT(*) as quantity
FROM
TableName
GROUP BY
CustomerID,
ProductID,
Title
Using Max will get you the most recent order
SELECT CustomerID, MAX(OrderId), ProductID, Title
FROM table
GROUP BY CustomerID, ProductID, Title
OR
Using Min will get you the first order
SELECT CustomerID, MIN(OrderId), ProductID, Title
FROM table
GROUP BY CustomerID, ProductID, Title
Provided that it's really what you want you can get the first order of each order with the same customer, product and title using a grouping and the MIN function (MAX would give you the last order):
SELECT CustomerID, MIN(OrderID) AS OrderID, ProductID, Title
FROM MyTable
GROUP BY CustomerID, ProductID, Title
If you want the number of duplicate orders (that would be the ordered quantity judging by your question) you can add a count:
SELECT CustomerID, MIN(OrderID) AS OrderID, ProductID, Title,
COUNT(*) AS Quantity
FROM MyTable
GROUP BY CustomerID, ProductID, Title