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

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

Related

Aggregating column values based on range

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.

SQL MIN() with GROUP BY select additional columns

I am trying to query a sql database table for the minimum price for products. I also want to grab an additional column with the value of the row with the minimum price. My data looks something like this.
ProductId | Price | Location
1 | 50 | florida
1 | 55 | texas
1 | 53 | california
2 | 65 | florida
2 | 64 | texas
2 | 60 | new york
I can query the minimum price for a product with this query
select ProductId, Min(Price)
from Table
group by ProductId
What I want to do is also include the Location where the Min price is being queried from in the above query. Is there a standard way to achieve this?
One method uses a correlated subquery:
select t.*
from t
where t.price = (select min(t2.price) from t t2 where t2.productid = t.productid);
In most databases, this has very good performance with an index on (productid, price).

MS Access 2007 query pulls same records multiple times

I have a problem, my query in MS Access 2007 pulls same records multiple times.
There are two tables : sales, products
Product Table
ID | Name | Price | Code
01 | PEN | 0.10$ | 01
02 | ITEM | 0.20$ | 2567
Sales table:
ID | Code | Amount
1 | 01 | 4
2 | 2567 | 2
And there's query
SELECT Product.Name, Product.Price, Sales.Amount
FROM Product, Sales
WHERE Product.Code IN (SELECT Sales.Code FROM Sales);
Thats the result
Name Price Amount
PEN $0.10 4
PEN $0.10 4
ITEM $0.20 2
ITEM $0.20 2
Change your query to
SELECT Product.Name, Product.Price, Product.Amount
FROM Product, Sales
WHERE Product.Code = Sales.Code;
Your query is currently joining every record in Product to every record in Sales, resulting in multiples. You need to do a join between them, either in the WHERE clause like Yousaf suggested, or like this, which is more the standard way to do it:
SELECT Product.Name, Product.Price, Sales.Amount
FROM Product
INNER JOIN Sales ON Product.Code = Sales.Code

Database design for products with multiple units

I am designing a database for retail business using Sql server as backend. There are some products that can be sold in multiple units, for example, pencils can be sold in ea and dozen, paper can be sold in sheet, ream, and canton. Basically, each product can be sold in more than one unit.
The App needs to supports
Can receive products from suppliers in many unit. Sometime we might
order 1 pencil and the next time we order 2 boxes of pencil.
Can sell products in multiple unit, for example, we must be able to
sell 1 box and 2 pencils in the same bill.
App also need supports for FIFO or LIFO
Below is my initial design
Table: Products
ProductId | Barcode | Name | BaseUnitId
1 | XXXX | Pencil | 1
Table: Units
UnitId | Name
1 | Each / Pieces
2 | Box
Table: UnitConversion
ProductId | BaseUnitId | Multiplier | ToUnitId |
1 | 1 | 24 | 2 | // 24 pencils in a box
Table: Inventories
Id | ProductId | UnitId | Quantity
1 | 1 | 1 | 48 //In pieces
Table Invoices
Id | ProductId | UnitId | Quantity
1 | 1 | 2 | 1.5 //Sold/Purchased 1.5 boxes that means 18 pieces
Is there any flaws in my design? Is there anything that I miss? This can't be a new problem. Does anyone have any ideas (or examples)?
I have a few suggestions:
It seems like you could remove the UnitConversion table and just store the Multiplier value against the Unit record (so you'd store 1 against Each / Pieces and 24 against Box). Then the conversion would just be the 'From' unit's quantity divided by the 'To' unit's quantity.
Is is possible that different units would have different barcodes? If so, the barcode could be stored against the Unit record instead.
In your Inventories and Invoices tables, the ProductId column might be unnecessary as you could get this by joining Units table.
To support FIFO or LIFO, you're going to need to store more specific information about your stock, so there's some way of knowing the date it was booked in, the quantity remaining, and maybe some way of identifying that specific item (or group of items).
Hope this helps!
EDIT: Your Inventories table could look something like this:
Id | UnitId | [identifier] | CurrentQuantity | DateAdded
1 | 1 | ABC123 | 20 | 2017-01-10
2 | 1 | ABC124 | 96 | 2017-01-12
The [identifier] column (name's up to you!) would store some way of identifying the physical stock, this could be something that the users assign on receipt of the item, or maybe their suppliers would already have added some that could be used.
To implement FIFO in a scenario where someone wants to buy 24 pencils, you know you need to take 20 from the group of items labelled 'ABC123' and 4 labelled 'ABC124'.

Access SQL query update calculation for duplicates

I have a query that filters results for products which have had orders sent after an user-input date, and calculates what the quantity becomes if the order was sent after that date.
SELECT *, [OnHand]+[OrderJoin.Quantity] AS Qty After
FROM Query3
WHERE (((Query3.ShippedDate)>[Enter End Date] And (Query3.ShippedDate) Is Not Null));
However, I need a way for it to recognise duplicates and update it based on those.
e.g. I have this
ID | Product Name | Qty Before | Qty Shipped | Qty After
11 | Chocolate | 80 | 20 | 100
11 | Chocolate | 80 | 10 | 90
And I'd need a way for it to show Qty After as 110 (after the 10 and 20 shipped)
If I understand correctly, you want an aggregation query. This would be something like this:
SELECT id, ProductName,
OnHand]+ SUM([OrderJoin.Quantity]) AS Qty After
FROM Query3
WHERE Query3.ShippedDate > [Enter End Date] And
Query3.ShippedDate) Is Not Null
GROUP BY id, ProductName, OnHand;
I note that OrderJoin is not defined, but that is the structure of your original query.