SQL-Script to Automatically build pallets - sql

I have code that I am using to call out how many pallets an item would be able to build. The issue I am having is I cannot figure out how to then automatically build pallets based on this number.
For example, if I have an item that can build 3.50 pallets, then I would want that to go into a new table that will then call out Pallet #1 and then a unique name, Pallet #2 then a unique name, Pallet #3 then a unique name. There will then be left over of .50.
I would want to then look in the category and find a ITEM that could fit with the .50 pallet item and try to make a whole pallet. In the table below, the remaining .50 of ITEM '1111' would be paired with ITEM '3333' which is .350 to then make Pallet #4, this process would then loop and find all the other combos based on the category to make the closest full pallet.
Ideally I would like the first pallets to be made on anything greater then 1, by giveng them a unique name, then using the leftovers to combine with other leftovers(items <1) to make other potentially full pallets, with a threshold of between 1 and .85:
ITEM CUBIC_INCHES PALLETS CATEGORY RANKING
1111 100,000 3.50 HIGH_TOP 1
2222 50,000 1.75 LOW_TOP 1
3333 10,000 .350 HIGH_TOP 2
4444 5,000 .175 LOW_TOP 2
My code that I am using to make this table is:
SELECT
ITEM
,CUBIC_INCHES
,CAST(CASE WHEN CUBIC_INCHES=0 THEN 0
ELSE (CUBIC_INCHES)/28,571.42 END AS DEC(38,4)) AS PALLETS
,CATEGORY
,RANK() OVER (PARTITION BY CATEGORY ORDER BY CUBIC_INCHES) AS RANKING
FROM TABLE_1

Related

Backfill data based or insert new records based on matching criteria

I have the following effective dated table with several thousands records that would need to be updated/inserted based on certain criteria.
Table Car_Specification:
Effective_Date
Car_ID
Num_Wheels
Num_Doors
Engine_Type
Color
01-MAR-2021
C001
4
2
Turbo
Red
01-APR-2021
C001
4
2
Turbo
Blue
01-JUN-2021
C001
4
2
Turbo
Green
Lookup Car_Change:
Effective_Date
Car_ID
Num_Wheels
Num_Doors
Engine_Type
Color
01-MAR-2021
C001
4
2
Turbo
White
01-MAY-2021
C001
4
2
Manual
Red
Every day, changes to a car is captured inside the Car_Change table and the updates will need to be updated into Car_Specification table based on Car_ID and Effective_Date.
In the example above, I would like to query Car_Specification for the list of effective_date and car_id and perform a lookup into Car_Change table, if a match based on effective_date and car_id is found, I will update the data in the Car_Change with the data in the Car_Specification table for those fields that matches. The changes will also need to be forward filled or propagated forward.
If the effective_date and car_id doesn't match but there is a change in Car_Change, I will need to insert the new effective_date and car_id into Car_Specification and forward fill the changes.
For instance, C001 will show the following after the update:
Effective_Date
Car_ID
Num_Wheels
Num_Doors
Engine_Type
Color
01-MAR-2021
C001
4
2
Turbo
White
01-APR-2021
C001
4
2
Turbo
White
01-MAY-2021
C001
4
2
Manual
Red
01-JUN-2021
C001
4
2
Manual
Red
I am thinking along the line of using the MERGE UPDATE/INSERT construct to handle the changes. Would like to seek advice on the most efficient way to handle such changes given the tables are large and I am looking to do the update/insert operation on a daily basis to keep my data inside Car_Specification updated. If I am going ahead with MERGE, how do I handle the forward filling of data?
As a frame challenge. Several thousands of records is a tiny data set; you do not need to merge the data. Just have a single row for each car in Car_Specification for the original specification and then if there are changes put them into Car_Changes and when you want to display the latest value then select the last change, or the specification if there were no changes.
SELECT COALESCE(c.effective_date, s.effective_date) AS effective_date,
s.car_id,
COALESCE(c.num_wheels, s.num_wheels) AS num_wheels,
COALESCE(c.num_doors, s.num_doors) AS num_doors,
COALESCE(c.engine_type, s.engine_type) AS engine_type,
COALESCE(c.color, s.color) AS color
FROM car_specification s
LEFT OUTER JOIN LATERAL(
SELECT *
FROM car_changes c
WHERE c.car_id = s.car_id
AND c.effective_date >= s.effective_date
ORDER BY c.effective_date DESC
FETCH FIRST ROW ONLY
)
ON (1 = 1) -- The join condition is inside the lateral join.
If you want you can wrap it in a view.

Database Design: Order Items with quantities spanning multiple statuses

I have a requirement to create a database that holds orders with items for each order.
This would be the traditional table setup
Order Table
Id (pk)
CustomerId (fk)
1
1
Item Table
Id (pk)
OrderId (fk)
StatusId (fk)
Quantity
1
1
1
1000
ItemStatus Table
(Don't worry about how the data knows which status is first, second, third, etc)
Id (pk)
Name
Description
IsStart
IsTerminal
1
New
For newly created items
1
0
2
Materials Ordered
For indicating that raw materials are ordered
0
0
3
Pre-Fabrication
For receiving materials and gathering other resources
0
0
4
In Work
For indicating that the assembly process is underway
0
0
5
Staging
For preparing the items for shipping
0
0
6
Shipped
For indicating that items are complete and no longer in the facility
0
1
However
I have the requirement to take the above quantity of 1000 and break it down by status as it pertains to the business workflow.
My initial implementation looked something like this, but I wanted to reach out and see if there is a better design.
Modified Item Table
Id (pk)
OrderId (fk)
1
1
QuantityBreakdown Table
Id (pk)
OrderItemId (fk)
StatusId (fk)
Quantity
1
1
2
200
2
1
3
200
3
1
4
400
4
1
5
200
Edit
Here are some examples in layman terms to help clarify expected solution. All scenarios will be simplified by only having a single item. Also, the handling of ordering materials is out of scope; I just need to know that the item is waiting.
In these examples, we will be handling the creation process of a burger (item #1). In more advanced scenarios, we could add another ITEM such as fries (that would be item #2)
Example 1
A restaurant order is created with 1 burger. All materials needed for the assembly of the burger are on-hand; therefore, the burger will progress through the statuses with all quantities (New => Prep => Cooking => Packaged => Delivered).
Example 2
A restaurant order is created with 2 burgers. Only enough materials for one burger are on-hand; therefore, the item quantity needs to be split. Since we don't want the customer waiting, the first burger will progress through the statuses with a quantity of 1. While the second burger will have to wait in a new status called Pending. Then once the materials are available, the second burger may continue the workflow.
Well I cannot just comment to ask for clarifications.
But I would have each OrderItem be its on distinct item in an order with its own Status (status in OrderItem). So if in fact you had 4 sets of the same item, each would have its own status.
You could always group-by if you want the total # of each OrderItemId

sum not calculating correct no. of units in SQL command

I have the following SQL script(of which the result is displayed under the script). The issue I am having is that I need to add up the quantity on the invoice. The quantity works fine when all the products on the invoice are different. When there is a product that appears twice on the invoice, the result is incorrect. Any help appreciated.
The DISTINCT keyword acts on all columns you select.
A new product introduces a difference which makes it no longer distinct. Hence the extra row(s).
Where you had:
Order Product Total
1 Toaster $10
2 Chair $20
And another item is added to order 1:
Order Product Total
1 Toaster $99
1 Balloon $99 -- Yes that's a $89 balloon!
2 Chair $20
The new row (balloon) is distinct and isn't reduced into the previous row (toaster).
To make is distinct again, don't select the product name:
Order Total
1 $99
2 $20
Uniqueness kicks in and everyone's happy!
If you can remove the column from the select list that's "different", you should get the results you need.

Challenging Excel VBA/Macro for inventory management

I work for an eCommerce company and we use Microsoft Excel for our inventory database. We currently just keep adding items to this database as we purchase them, without ever removing them. What I would like to do is start removing items as they sell. I am not sure how to attach the file, so if you e-mail me at drenollet#supplykick.com I can send it to you. Below are the following steps:
The Sales tab includes the sales data for the items. I would like to take this data and be able to copy and paste it in a sheet in our Inventory Managment file in excel (a separate file, but I included a sample in the "Database" sheet).
I then need to just use a VLOOKUP formula and the Catalog data to get the Product ID instead of the SKU. (I can do this.)
Then use the copied data in the Sales Tab that is in the Inventory Management file and move the corresponding rows out of the Database file/sheet to the Sold Items sheet.
A few thoughts on specifics:
I want to make sure all the quantities are right. (e.g.1 if we purchased two of an item and only one sold - reducing the quantity in the Database sheet from two down to one.) (e.g.2 If we purchased an item two different times at two different prices and both were purchased in one sale, I would want to make sure both of the rows are moved out of the database).
If you have any thoughts on making sure the quantities are right, let me know. Maybe we need to set all the purchase quantities to one and copy the purchase of a multiple quantity of items X number of times for each one that was purchased.
Would love your input on how to cross this bridge! Let me know if you would like to see the sample file and I can directly e-mail it to you!
Best Regards,
Don Renollet
The best way to do this is to have a sheet called Movements
then you have just rows of entries like
A B C D
----------------------------------------
prodID Movement type Qty Date
123 Purchase 5 08/01/15
789 Sale 2 07/01/15
123 Return 1 06/01/15
456 Sale 1 05/01/15
789 Purchase 10 04/01/15
456 Purchase 5 03/01/15
123 Sale 2 03/01/15
123 Return 1 02/01/15
123 Sale 1 02/01/15
123 Purchase 10 01/01/15
Then at anytime excel can calculate whats in stock using sumifs or similar
=SUMIFS(C:C,A:A,"123",B:B,"Purchase") - Sumif(C:C,A:A,"123",B:B,"Sale")) + Sumif(C:C,A:A,"123",B:B,"Return"))
You should never remove rows from a database like this, you can always do a stock take every so often and restart the database with 1 entry for each item, but aways store the old data elsewhere.
Try not to mix price with quantity if possible, if you need to manage price , consider using a moving average price (MAP)

SELECT datafields with multiple groups and sums

I cant seem to group by multiple data fields and sum a particular grouped column.
I want to group Person to customer and then group customer to price and then sum price. The person with the highest combined sum(price) should be listed in ascending order.
Example:
table customer
-----------
customer | common_id
green 2
blue 2
orange 1
table invoice
----------
person | price | common_id
bob 2330 1
greg 360 2
greg 170 2
SELECT DISTINCT
min(person) As person,min(customer) AS customer, sum(price) as price
FROM invoice a LEFT JOIN customer b ON a.common_id = b.common_id
GROUP BY customer,price
ORDER BY person
The results I desire are:
**BOB:**
Orange, $2230
**GREG:**
green, $360
blue,$170
The colors are the customer, that GREG and Bob handle. Each color has a price.
There are two issues that I can see. One is a bit picky, and one is quite fundamental.
Presentation of data in SQL
SQL returns tabular data sets. It's not able to return sub-sets with headings, looking something a Pivot Table.
The means that this is not possible...
**BOB:**
Orange, $2230
**GREG:**
green, $360
blue, $170
But that this is possible...
Bob, Orange, $2230
Greg, Green, $360
Greg, Blue, $170
Relating data
I can visually see how you relate the data together...
table customer table invoice
-------------- -------------
customer | common_id person | price |common_id
green 2 greg 360 2
blue 2 greg 170 2
orange 1 bob 2330 1
But SQL doesn't have any implied ordering. Things can only be related if an expression can state that they are related. For example, the following is equally possible...
table customer table invoice
-------------- -------------
customer | common_id person | price |common_id
green 2 greg 170 2 \ These two have
blue 2 greg 360 2 / been swapped
orange 1 bob 2330 1
This means that you need rules (and likely additional fields) that explicitly state which customer record matches which invoice record, especially when there are multiples in both with the same common_id.
An example of a rule could be, the lowest price always matches with the first customer alphabetically. But then, what happens if you have three records in customer for common_id = 2, but only two records in invoice for common_id = 2? Or do the number of records always match, and do you enforce that?
Most likely you need an extra piece (or pieces) of information to know which records relate to each other.
you should group by using all your selected fields except sum then maybe the function group_concat (mysql) can help you in concatenating resulting rows of the group clause
Im not sure how you could possibly do this. Greg has 2 colors, AND 2 prices, how do you determine which goes with which?
Greg Blue 170 or Greg Blue 360 ???? or attaching the Green to either price?
I think the colors need to have unique identofiers, seperate from the person unique identofiers.
Just a thought.