Thank you in advance for reading!
The question I'm trying to answer is: "How much do parts really cost to make?" We manufacture by machining raw metal billets down to metal parts. Final parts are sold to a customer and scrap metal from the process is sold to the scrap yard.
For business/ERP configuration reasons our scrap vendor is listed as a customer and we ship him 'parts' like our other customers. These dummy parts are simply for each of the metal alloys we work with, so there is one dummy scrap part for each alloy we use. The scrap shipments are made whenever we fill our scrap bins so there's no defined time interval.
I'm trying to connect the ship date of a real part to a real customer to the closest scrap ship date of the same alloy. Then I can grab the scrap value per pound we were paid and include it in our revenue for the parts we make. If I can ask for the world it would be helpful to know how to grab the scrap shipment immediately before or immediately after the shipment of a real part - I'm sure management will change their minds several times debating if they want to use the 'before' or 'after' number.
I've tried other solutions and can't get them to work. I'm crying uncle, I simply can't get it to work....the web SQL interface our ERP uses claims it's T-SQL... thank you for reading this far!
What I'd like the output to look like is:
Customer Part Price Alloy Weight_Lost Scrap_Value Ship_Date
ABC Widget1 99.99 C182 63 2.45 10-01-2016
Here's the simplest I can boil the tables down to:
SELECT
tbl_Regular_Sales.Customer
tbl_Regular_Sales.Part
tbl_Regular_Sales.Price
tbl_Regular_Sales.Alloy
tbl_Regular_Sales.Weight_Lost
tbl_Scrap_Sales.Price AS 'Scrap_Value'
tbl_Regular_Sales.Ship_Date
FROM
(SELECT P.Part
,P.Alloy
,P.Price
,S.Ship_Date
,S.Customer
FROM Part AS P
JOIN S AS S
ON S.Part_Key = P.Part_Key
WHERE Shipper.Customer = 'Scrap_Yard'
) AS tbl_Scrap_Sales
JOIN
(SELECT P.Part
,P.Weight_Lost
,P.Alloy
,P.Price
,S.Ship_Date
,S.Customer
FROM Part AS P
JOIN S AS S
ON S.Part_Key = P.Part_Key
WHERE Shipper.Customer <> 'Scrap_Yard' ) AS tbl_Regular_Sales
ON
tbl_Regular_Sales.Alloy = tbl_Scrap_Sales.Alloy
AND <Some kind of date JOIN to get the closest scrap shipment value>
Something like this may do the trick:
WITH cteScrapSales AS (
SELECT
P.Alloy
,P.Price
,S.Ship_Date
FROM Part AS P
JOIN Shipper AS S ON S.Part_Key = P.Part_Key
WHERE S.Customer = 'Scrap_Yard'
), cteRegularSales AS (
SELECT
P.Part_Key
,P.Part
,P.Weight_Lost
,P.Alloy
,P.Price
,S.Ship_Date
,S.Customer
FROM Part AS P
JOIN Shipper AS S ON S.Part_Key = P.Part_Key
WHERE S.Customer <> 'Scrap_Yard'
)
SELECT
C.Customer
,C.Part
,C.Price
,C.Alloy
,C.Weight_Lost
,C.Scrap_Value
,C.Ship_Date
FROM (
SELECT R.*, S.Price AS Scrap_Value, ROW_NUMBER() OVER (PARTITION BY R.Part_Key ORDER BY DATEDIFF(SECOND, R.Ship_Date, S.Ship_Date)) ix
FROM cteRegularSales R
JOIN cteScrapSales S ON S.Allow = R.Allow AND S.Ship_Date > R.Ship_Date
) AS C
WHERE C.ix = 1;
Related
I have a simple manufacturing job card system that track parts and labor for an assigned job.
It consists of a JobHeader table that holds the Job Card number (JobHeader.JobNo), ID of the part being manufactured (JobHeader.RegNo) and quantity to be manufactured (JobHeader.RegNo).
There is a child table (JobLabour) that tracks all the times that have been worked on the job (JobLabour.WorkedTime)
I'm looking for a query that will return the average time taken to produce a part accross the last 5 job cards for that particular part.
The following query
SELECT TOP 5 JobHeader.RegNo, JobHeader.BOMQty, sum(JobLabour.WorkedTime) AS TotalTime FROM JobHeader INNER JOIN JobLabour ON JobHeader.JobNo=JobLabour.JobNo
WHERE JobHeader.RegNo='RM-BRU-0134'
GROUP BY JobHeader.BOMQty, JobHeader.JobNo, JobHeader.RegNo
will return this:
But what I'm looking for is a query that will return the average BOMQty and average totalTime. Something like this:
Is there a way to do this?
Your question explicitly mentions the "last five" but does not specify how that is determined. Presumably, you have some sort of date/time column in the data that defines this.
In SQL Server, you can use apply:
select jh.*, jl.*
from jobheader jh outer apply
(select top (5) avg(BOMQty) as avg_BOMQty, avg(totalTime) as avg_totalTime
from (select top (5) jl.*
from joblabour jl
where jl.regno = jh.regno
order by jl.<some datetime> -- however you determine the last five
) jl
) jl;
You can add a where clause to the outer query to filter on one or more particular jobs.
If I understand you correctly this will do the work
this will work for 1 RegNo='RM-BRU-0134' at a time
with topFive as (
SELECT TOP 5 JobHeader.RegNo, JobHeader.BOMQty, sum(JobLabour.WorkedTime) AS TotalTime
FROM JobHeader
INNER JOIN JobLabour ON JobHeader.JobNo = JobLabour.JobNo
WHERE JobHeader.RegNo = 'RM-BRU-0134'
GROUP BY JobHeader.BOMQty, JobHeader.JobNo, JobHeader.RegNo
)
select RegNo, avg(BOMQty) as BOMQty, avg(TotalTime) as TotalTime
from topFive
group by RegNo
Before I continue I do want to say this is FOR homework for my class. We are using SQL in Microsoft Access. With the transition to online classes because of covid-19 and my professor developing the virus last month we have not have had time to really dive much into how SQL works. I will also provide a picture of the ER Diagram I have of the database to hopefully provide a clear picture of what I'm trying to achieve. https://imgur.com/a/4QGRgRc
Now the question I'm given to solve is this:
Retrieve the phone number of the customer(s), who lives in Tyler, TX, booked two rooms on Jan 1, 2020.
The code I have written so far is as follows
SELECT CUSTOMER.Phone_No, CUSTOMER.Address, RESERVATION.Reservation_No, INCLUDES.Check_in, ROOM.Room_No
FROM CUSTOMER, RESERVATION, INCLUDES, ROOM
SELECT CUSTOMER.Phone_No, WHERE CUSTOMER.Address = 'Tyler, Tx' AND INCLUDES.Check_in < '12/31/2019' AND INCLUDES.Check_in > '01/01/2020'
I'm pretty stuck on where to go now or even if what I have so far will work. Could someone give me a point in the right direction on where I should go now?
If you just want customer info, use an aggregate query. Each field pulled must be included in GROUP BY clause:
SELECT Customer.ID, CustomerName, Phone_No FROM Customer INNER JOIN Reservation ON Customer.ID = Reservation.CustomerID WHERE Address = 'Tyler, Tx' AND Check_in BETWEEN #12/31/2019# AND #01/01/2020# GROUP BY Customer.ID, CustomerName, Phone_No HAVING Count(CustomerID) = 2;
Or take advantage of the power of nested query and IN() function:
SELECT * FROM Customer WHERE Customer.Address = 'Tyler, Tx' AND Customer.ID IN (SELECT CustomerID FROM Reservation WHERE Check_in BETWEEN #12/31/2019# AND #01/01/2020# GROUP BY CustomerID HAVING Count(*) = 2);
Or use DCount(). However, domain aggregate functions can slow query performance.
SELECT * FROM Customer WHERE Customer.Address = 'Tyler, Tx' AND DCount("*", "Reservation", "Check_in BETWEEN #12/31/2019# AND #01/01/2020# AND CustomerID=" & Customer.ID) = 2;
Can someone please help me with this issue? I've scoured the Internet looking at dozens of examples, but i just can't find a solution that works.
I am using Access 2013. The problem is that I am trying to make a query that will highlight all part numbers from a supplier that either has customer back orders and/or overdue deliveries.
I am using three tables:
tbl_Inventory_Master which I require the part number, on hand stock value, and the supplier code.
For any back orders I need to join the tbl_Customer_Back_Order table as I need the count of back order lines and the sum of the back order quantity.
If the supplier has a late delivery, then I need to add the tbl_On_Order table showing the count of overdue deliveries and the sum of the overdue quantities.
The query is retrieving the data but the returned quantities are double what they should be.
SELECT
I.Inventory_Part_Num, I.Description, I.On_Hand_Stock,
COUNT (B.Part_Number) AS Back_Order_Count, SUM(B.Back_Order_Qty) as BO_Qty,
COUNT(O.Part_Number) AS Late_Deliveries_Count, SUM(O.Order_Qty) AS Late_Qty
FROM (tbl_Inventory_Master AS I
LEFT OUTER JOIN tbl_Customer_Back_Order AS B
ON I.Inventory_Part_Num = B.Part_Number)
LEFT OUTER tbl_On_Order AS O
ON I.Inventory_Part_Num = O.Part_Number
WHERE
I.Customer_Code = '274' AND
O.Due_Date < [ENTER TODAYS DATE IN FORMAT DD/MM/YYYY]
GROUP BY I.Inventory_Part_Num, I.Description, I.On_Hand_Stock
For example, for the part number 2022940 I should have 10 back order lines and an overdue quantity of 43. Instead, the query is returning 20 back order lines and an overdue quantity sum of 86.
From the on order table I have three orders totaling 144 pieces, instead the query is returning 960.
Can someone please advise, as this is driving me crazy?
You are joining along unrelated dimensions, so you need to aggregate before joining:
SELECT I.Inventory_Part_Num, I.Description, I.On_Hand_Stock,
B.Back_Order_Count, B.BO_Qty,
O.Late_Deliveries_Count, O.Late_Qty
FROM (tbl_Inventory_Master AS I LEFT OUTER JOIN
(SELECT B.Part_Number, COUNT(*) as Back_Order_Count,
SUM(B.Back_Order_Qty) as BO_Qty
FROM tbl_Customer_Back_Order AS B
GROUP BY B.Part_Number
) as B
ON I.Inventory_Part_Num = B.Part_Number
) LEFT JOIN
(SELECT O.Part_Number, COUNT(O.Part_Number) AS Late_Deliveries_Count,
SUM(O.Order_Qty) AS Late_Qty
FROM tbl_On_Order AS O
WHERE O.Due_Date < [ENTER TODAYS DATE IN FORMAT DD/MM/YYYY]
GROUP BY O.Part_Number
) as O
ON I.Inventory_Part_Num = O.Part_Number
WHERE I.Customer_Code = '274';
Notice the outer aggregation is no longer needed.
I've got a query which gets the lists of customers who've made a purchase of the product for the current day
select Customer.customerName, sum(InvoiceDetail.itemPrice * InvoiceDetail.itemQuantity) as dailyPurchase from Invoice
inner join InvoiceDetail on Invoice.invoiceID = InvoiceDetail.invoiceID
inner join Customer on Invoice.customerID = Customer.customerID
inner join Item on InvoiceDetail.itemID = Item.itemID
inner join Branch on Branch.branchID = Invoice.branchID
inner join Region on Region.regionID = Branch.regionID
where
Invoice.inactive = 0 and InvoiceDetail.inactive = 0
and Item.itemTypeID = 3
and Region.regionCode = 'CR'
and cast(Invoice.invoiceDate as date) = convert(date, '01/08/2016', 103)
group by Customer.customerName
What I need is a table with a list of all the dates in the current month, listing ALL customers who have at least purchased the product ONCE. It should resemble something similar to this image here.
Any help on how to get started or a general idea of how to get the desired result, is much appreciated. Thanks!
Sample Data from Results:
customerName dailyPurchase
AGH COMMUNICATIONS 450.00
ARIEL AMARCORD SHOP 285.00
AKN COMMUNICATION 300.00
AWSDAC TELECOMMUNICATION 2850.00
BARLEY MOBILE & SERVICES 285.00
Table Structure - I'm sorry, I don't know an easier way to copy this.
First get the customers who have purchased the product atleast once this month alongwith date.
Then use pivot to get the result in the form that you want (as seen in image). Search stackoverflow for pivot in sql server, you will get good info.
Give some information about the table structure and sample data and I might be able to help you with the query to get the results.
I have two tables, one with data for materials and what costing lot size they currently have. Then I have another table containing purchase scales for the same materials. I then need to fetch the purchase scale that are the same or smaller than my costing lot size from the original table and the purchase scale just above it. This works for me as a correlated sub query within my select sentence:
Select
mbew.Matnr as Material
,mbew.bwkey as Plant
,mbew.STPRS/mbew.peinh as Standard_price
,mbew.verpr/mbew.peinh as Average_price
,keko.Costing_lot_size
,Keko.Costing_date
,(select max(info.scale_quantity_konm) as Scale_quantity from dwh.inforecords info where mbew.matnr = info.material and keko.costing_lot_size >= info.scale_quantity_konm) as Current_Costing_Lot_Size
,(select min(info.scale_quantity_konm) as Scale_quantity from dwh.inforecords info where mbew.matnr = info.material and keko.costing_lot_size < info.scale_quantity_konm) as Next_Costing_Lot_Size
,inforecords_larger_price.amount_dkk_konm as Next_Costing_Lot_Size_Price
from
mbew mbew
left join
(Select kekoa.Material, kekoa.Plant, kekoa.Costing_date, kekoa.Costing_lot_size
from sap.keko Kekoa
inner join
(select Material, Plant, max(costing_date) as Lates_costing_date from sap.keko
group by material, plant) kekob
on kekoa.costing_date = kekob.Lates_costing_date
and kekoa.Material = kekob.material
and kekoa.plant = kekob.plant) as keko
on
mbew.matnr = keko.material
and mbew.bwkey = keko.Plant
But it is highly inefficient. Can it somehow be made smarter/optimized?
Thanks in advance