Aggregating column values based on range - sql

I'm new to SQL and stackoverflow, forgive if my question is trivial. I have record of customers purchase quantities in a table, so I want a count of customers whose purchase fall in a range.
TABLE:
+-------------+----------------+
| customer_id | order_quantity |
+-------------+----------------+
| 123 | 10000 |
| 143 | 5000 |
| 999 | 200000 |
| 555 | 50000 |
+-------------+----------------+
The goal is to count how many customers buy < 5000, between 5000-50000 and 50000-100000 order quantities.
I used:
SELECT customer_id,
CASE
WHEN COUNT(order_quantity) < 5000
....
FROM purchases
Which isn't correct (don't even work).

You can use:
select (case when order_quantity < 5000 then '[0-5000)'
when order_quantity < 10000 then '[5000-10000)'
else '10000+'
end) as grp,
count(*) as num_purchases,
count(distinct customer_id) as num_customers
from t
group by grp
order by min(order_quantity);
If a customer makes more than one purchase in a given group, it is not clear if you want to count the number of purchases or the number of customers. This does both.

Related

Sum Total of Distinct Items In Table

I have a table of transactions. One column is for the vendor ID, and one column is for the amount due. [There are other columns, but they aren't relevant]
id | amount | custid
23 | -31.32 | 904424
24 | -19.94 | 646744
25 | -4.77 | 904424
26 | -29.40 | 972979
I want to run a query that delivers the total for each distinct customer ID.
The goal is to determine how much each customer is owed.
That's basic aggregation:
select custid, sum(amount) total_amount
from mytable
group by custid

Counting distinct stores SQL

I am fairly new to SQL and was wondering if anyone could help with my code.
I am trying to count the distinct number of stores that are tied to a certain Warehouse which is tied to a purchase order.
Example: If there are 100 stores with this PO that came from Warehouse #2 or #5 or etc... then I would like:
| COUNT_STORE | WH_LOCATION |
1 | 100 | 2 |
2 | 25 | 5 |
3 | 56 | 1 |
[]
My Code:
select count(distinct Store_ID) as Count_Store, WH_Location
from alc_Loc
where alloc_PO = 11345
group by Store_ID, WH_Location
When I run this I get a 1 for "count_store" and it shows me the WH_Location multiple times. I feel as if something is not tying in correctly.
Any help is appreciated!
Just remove store_id from the group by:
select count(distinct Store_ID) as Count_Store, WH_Location
from alc_Loc
where alloc_PO = 11345
group by WH_Location;
When you include Store_ID in the group by, you are getting a separate row for each Store_ID. The distinct count is then obviously 1 (or 0 if the store id is NULL).

Finding top 5 worst performing customers by salesperson

I have a view that returns data as follows:
| salesman | customer | invoiced | budgeted | difference
|--------------|--------------|-------------|-------------|--------------
| Joe | ACME Ltd | 1000 | 2000 | -1 000
| Sam | Apple | 1500 | 1100 | +400
| Joe | Apple | 2000 | 2300 | -300
| Kim | ACME Ltd | 1000 | 1500 | -500
This is a snippet of of over 1500 rows that are returned. What I would like to do is return all rows by salesman showing that salespersons 5 worst customers sales. Each salesperson would therefore have 5 rows and each salesperson does sell to various customers who can be the same customer as another salesperson... right now I am looking at 5 worst customers by salesperson by value.
Any ideas on how I can achieve this?
Since one salesman can invoice the same company multiple times, you need to average the invoice amount across that group, then rank withing that partition and take the top five. If you are looking for the absolute worse sale per salesman then you would need to replace AVG with MIN.
SELECT
*
FROM
(
SELECT
salesman,
customer,
AverageInvoiced,
DescendingRank=DENSE_RANK() OVER(PARTITION BY salesman ORDER BY AverageInvoiced DESC)
FROM
(
SELECT
salesman,
customer,
AverageInvoiced=AVG(invoiced)
FROM
Table
WHERE
GROUP BY
salesman,
customer
)
)AS A
WHERE
DescendingRank<=5
I think you can use this
TRy This
SELECT
*
FROM
(
SELECT
salesman,
customer,
AverageDiffrence,
DescendingRank=DENSE_RANK() OVER(PARTITION BY salesman ORDER BY AverageDiffrence DESC)
FROM
(
SELECT
salesman,
customer,
AverageDiffrence=AVG(difference)
FROM
ireports_salesman_variance
WHERE
GROUP BY
salesman,
customer
)
)AS A
WHERE
DescendingRank<=5

How do I list my items by when they will be out of inventory

I have a table that lists items in my inventory, the total quantity on hand, order qty and ship date.
+-------+-----------+------------+----------+
| Items | QtyOnHand | QtyOrdered | ShipDate |
+-------+-----------+------------+----------+
| Itema | 100 | 80 | 3/4/14 |
| Itemb | 80 | 220 | 3/8/14 |
| Itema | 100 | 80 | 3/10/14 |
| Itemb | 80 | 100 | 3/12/14 |
+-------+-----------+------------+----------+
I would like a return like this that includes the item, date we are out of inventory and the amount over the inventory we are on that date.
Note: the same item is generally on the list multiple times and this is a representation of actual sales orders. The qty on hand number is the total on hand for that item TODAY and will be the same every time the item is listed.
My issue is that if item a ships 80 cases on 3/4/14 and has 100 on hand then with 20 left over the shipment of 80 cases on 3/10/14 will be 60 cases short so the query will return item a 3/10/14 -60. To indicate that based the current on hand values, on 3/10/14 item a will not have adequate inventory to cover the order.
Itemb 3/8/14 -140
Itema 3/10/14 -60
Any help would be greatly appreciated.
Ken
I think you may want something like this:
SELECT Items,ShipDate,(QtyOnHand-QtyOrdered)
from TableName
where (QtyOnHand-QtyOrdered) < 0
You haven't specified which DBMS you're using. MSSQL 2012 makes this fairly simple:
WITH cteInventory (Items, ShipDate, Stock) As
(
SELECT
Items,
ShipDate,
QtyOnHand - Sum(QtyOrdered) OVER (PARTITION BY Items ORDER BY ShipDate)
FROM
Inventory
)
SELECT
Items,
Min(ShipDate) As Date,
Max(Stock) As Stock
FROM
cteInventory
WHERE
Stock < 0
GROUP BY
Items
ORDER BY
Date
;
SQL Fiddle

Finding a date from a SUM

I am having trouble finding what date my customers hit a certain threshold in how much money they make.
customer_id | Amount | created_at
---------------------------
1134 | 10 | 01.01.2010
1134 | 15 | 02.01.2010
1134 | 5 | 03.24.2010
1235 | 10 | 01.03.2010
1235 | 15 | 01.03.2010
1235 | 30 | 01.03.2010
1756 | 50 | 01.05.2010
1756 | 100 | 01.25.2010
To determine how much total amount they made I run a simple query like this:
SELECT customer_id, SUM(amount)
FROM table GROUP BY customer_id
But I need to be able to find for e.g. the date a customer hits $100 in total amount.
Any help is greatly appreciated. Thanks!
Jesse,
I believe you are looking for a version of "running total" calculation.
Take a look at this post calculate-a-running-total.
There is number of useful links there.
This article have a lot of code that you could reuse as well: http://www.sqlteam.com/article/calculating-running-totals.
Something like having clause
SELECT customer_id, SUM(amount) as Total FROM table GROUP BY customer_id having Total > 100
I'm not sure if MySQL supports subqueries, so take this with a grain of salt:
SELECT customer_id
, MIN(created_at) AS FirstDate
FROM ( SELECT customer_id
, created_at
, ( SELECT SUM(amount)
FROM [Table] t
WHERE t.CustomerID = [Table].CustomerID
AND t.created_at <= [Table].created_at
) AS RunTot
FROM [Table]
) x
WHERE x.RunTot >= 100
GROUP BY customer_id