I have two tables stored in a MySQL database. The first contains pricing information about SKUs I want to sell tomorrow. The second contains historical sales and visitation data for SKUs. What I want to do is calculate the conversion rate (orders divided by visits) for each SKU at the price specified in the tomorrow's pricing table based on prior sales data at tomorrow's specified price, conditioned that the SKU at that price has at least 100 visits OR 50 visits and 1 order, and if not then I want it to add the visits and orders from the next highest price point.
I've created a table containing example data in an SQL fiddle
http://www.sqlfiddle.com/#!9/bf4273
Using the example data in the sqlfiddle, what I want to return then would be
ABC1, 100.0, 100, 0
ABC2, 75.0, 24, 0
ABC3, 35.0, 1312, 57
ABC4, 190, 55, 1
ABC5, 250, 72, 1
ABC6, 250.0, 80, 1
If you examine the data in the sql fiddle, you can see that ABC1 doesn't meet the count requirements at the specified $100 price point, so it rolls up the visits from the next higher price point, in that case 110, but keeps the reported price at 100.
ABC2 doesn't have enough visits at the specified price, but there aren't any visits at any other price point higher than the specified one, so it just returns the 24 and 0 visits.
ABC3 meets the requirements, so it just returns the specified value
ABC4 meets the > 50 visits and > 1 sale, so it's returned
ABC5 doesn't have enough visits and orders at the specified price, so it sums up the visits and orders to include the next highest price point. This logic is re-applied again if rolling up to the next highest price point still doesn't meet the requirements for 100 visits or 50 visits and 1 order.
ABC6 is similar to ABC5 except that now the orders at the specified price point for ABC6 for tomorrow is zero, but we still take the orders count from the next highest price point too (e.g. we sum up visits and orders from the next highest price point until we meet the necessary visits and/or orders requirements).
At the moment I've applied this logic inside Python, but it's a bit cumbersome and if possible I'd like to have it all in SQL. Can anyone help? Even telling me it's not possible to do this in MySQL would be valued.
Thanks,
Brad
Related
Here is the structure of 1st Table called Product.
PRODID PDESC PRICE CATEGORY DISCOUNT
101 BALL 10 SPORTS 5
102 SHIRT 20 APPAREL 10
Here is the structure of 2nd table called SaleDetail.
SALEID PRODID QUANTITY
1001 101 5
1001 101 2
1002 102 10
1002 102 5
I am trying to get total sales amount for each product by joining 2 tables. Here is the SQL i tried but its not giving correct result.
select a.prodid,
(sum((price - discount))),
sum(quantity),
(sum((price - discount))) * sum(quantity)
from product a
join saledetail b on a.prodid = b.prodid
group by a.prodid
2nd column of the query is giving incorrect final price. Please help me correct this SQL.
Please find an indicative answer to your question in the fiddle.
A problem stems from the aggregation of the difference of price. In case that the same product has two different prices, then these prices would be aggregated to one.
Moreover, you multiple the sums of the prices and quantities, while you need to perform the calculation on every sample. Look at the answer by #DanteTheSmith.
You might consider to use the SaleDetail table on the left side of your query.
SELECT SD.PRODID,
P.Price-P.Discount AS Final_Price,
SUM(SD.QUANTITY) AS Amount_Sold,
SUM((P.Price-P.Discount)*SD.QUANTITY) AS Sales_Amount
FROM SaleDetail AS SD
JOIN Product AS P
ON SD.PRODID = P.PRODID
GROUP BY SD.PRODID, P.Price-P.Discount
It would help if you built the example in SQL fiddle or gave the creates for the tables, but if I have to guess your problem is:
(sum((price - discount))) * sum(quantity)
needs to be:
sum((price - discount) * quantity)
(price - discount) * quantity is the function you wanna apply PER ROW of the joined table then you wanna add all those up with SUM() when grouping by prodid.
Furthermore, you can notice that (price - discount) needs to be done ONLY ONCE PER ROW so a quicker version would be to do:
(price-discount) * sum(quantity)
That would give you the total money earned for that product across all the sales you made, and I am guessing this is what you want?
I just notice you have a problem with 2nd column, dunno if that has been in question all along:
(sum((price - discount)))
Why are you summing? Do you want the money earned per product per unit of the product? Well guess what, your price is the same all the time, same as your discount so you can simply go with:
(price-discount) as PPP
NOTE: This assumes the discount is numerical (not percentage) and is applicable to all your sales, also the price is forever the same all which is not real life like.
I have to do a query that shows training completion dates for all employees. The end result would be the number of employees that attended company trainings each quarter.
I have setup the query to have the user enter a start and end date for it (example 1/1/17 - 3/31/17) which works and a total row which also works. The issue I am having is I only want the count to include the records that fall within that range.
EXAMPLE
Employee Name Training1 Training2 Training3 Training4
Noname 07/06/17 1/12/17 2/15/17 6/6/17
COUNT 1 1 1 1
I know the query above is right because 2 pieces of the record fit the puzzle however, 2 pieces do not. How can I make my query work to only count what fits in the given date range? So COUNT should be 0, 1, 1, 0?
I'm using Mysql (not MSSQL) database and bumped onto a problem I seem to be unable to solve. I would very much appreciate your help finding a solution.
I'd like to create a view using two tables, as described below:
1. product_in
product_code
received_time
received_amount
2. product_out
product_code
delivery_time
delivered_amount
The “view” should provide the following:
product_code
received_time
received_amount
of_which_delivered
My problem is that product_out is to be administered to the first incoming data (FIFO: first in first out), but since the amount delivered is either more or less than the received amount, I do not know how to calculate the “of_which_delivered”.
So far, I managed to put into order the incoming data, and sum up the outgoing (delivered) goods using SUM.
SELECT
sn,
product_code,
received_time,
received_amount,
delivered_amount
FROM
( SELECT
received_time,
received_amount,
#rend2 := If( #rend1 = product_code, #rend2 + 1, 1) as sn,
#rend1 := product_code AS product
FROM
product_in,
( SELECT #rend1 := 0, #rend2 := 0 ) AS tt
ORDER BY
product_code,
received_time ) AS k
LEFT JOIN
( SELECT
product_code AS prdct,
SUM(delivered_amount) AS delivered_amount
FROM
product_out
GROUP BY
product_code ) AS b
ON aru = product_code
I have not succeded in creating the loop that would make it possible to analyze if the output amount is more, or less than the received amount on a given day, and if more, then the difference be added to the received amount of another day.
To be more precise, here is an example:
Product Date Qty
nr.1 Sep 2 500
nr.1 Sep 3 300
nr1. Sep 4 200 on the 4th.
900 pcs were delivered out on the 5th.
In this case we should see the following in the view:
Product Action Date Qty
nr.1 received Sep 2 500 (delivered all 500)
nr.1 received Sep 3 300 (delivered all 300)
nr.1 received Sep 4 200 (only 100 delivered)
I would be very grateful to anyone who could help me find a solution!
Sorry no query adjustment for you, but... having worked with accounting systems in the past, your database structure appears short on a better handling of the in/out FIFO method (or even LIFO). What the underlying accounting system had was a inventory table for all receipts (abbreviated)
Table: ItemTrans
ItemTransID (auto-increment ID for any transaction)
ItemID (item id of the inventory item)
Status (status, such as In, Our or Inventory Adjustment)
Date (date of the activity)
Qty (quantity)
QtyUsed (running total column as inventory was used up)
As items were sold or adjustments. the Sales Details table would show which ItemTrans record the quantities were used for. So, if you had inventory on hand as you have in your sample, the sales order detail line would show the 900. The inventory used table would show which specific ItemTransID the quantities were allocated from and how many from said block, thus showing what your intended activity of release of actual product was at the time of sale.
This way, you don't have to recreate what inventory was what at a given point in time. Just query the sales order details and which items they were pulled from to get the data and how many from each block of receipt it went against.
This simplifies the process of generating the COGS (cost of goods sold) as would be reported to the General Ledger from a Sub-journal such as Accounts Receivable (Sales Orders) activity.
Do you have the ability to introduce such adjustments to your database structures?
I need to write an SQL Query for MySQL Database which gives me the data according to the necessary conditions
I have a table having structure like this
id: orderId
amount : itemAmount
rate : itemRate
time : orderTime
Now I have to select all the rows having same rates and then have to add all the items having same rates. This should work for each rate means for eg.
row with id 1 is having rate $20 with 2 items and row 3 is having rate $20 with 5 items
row with id 2 is having rate $40 with 4 items and row 4 is having rate $40 with 7 items
I should get result is
rate: $20 totalItem : 7
rate: $40 totalItem : 11
As I stated in my comment, I don't know what your columns are called, I'll assume in my answer they're called id, amount, rate and time.
SELECT rate, COUNT(*) AS totalItems -- Select the rate, and count everything
FROM theRelevantTable -- Use the rows in this table
GROUP BY rate -- But do the selection per group.
In clearer English:
Group the rows in theRelevantTable by their rate, then, for every group, give me the rate and count how many rows there are in the group.
I hope this is what you meant. I do not entirely understand your question.
maybe this? SQL FIDDLE to play with
ASSUMPTIONS: you have a table called orders with columns rate, amount, time, id.
amount stores a quantity of items, rate is the price they are at, and time is when it occurred.
SELECT
rate,
SUM(amount)
FROM orders
GROUP BY rate
I have a table with transactions. All transactions are stored as positive numbers, if its a deposit or withdrawl only the action changes. How do i write a query that can sum up the numbers based on the action
-actions-
1 Buy 2 Sell 5 Dividend
ID ACTION SYMBOL PRICE SHARES
1 1 AGNC 27.50 150
2 2 AGNC 30.00 50
3 5 AGNC 1.25 100
So the query should show AGNC has a total of 100 shares.
SELECT
symbol,sum(shares) AS shares,
ROUND(abs(sum((price * shares))),2) AS cost,
FROM bf_transactions
WHERE (action_id <> 5)
GROUP BY symbol
HAVING sum(shares) > 0
I was originally using that query when i had positive/negative numbers and that worked great.. but i dont know how to do it now with just positive numbers.
This ought to do it:
SELECT symbol, sum(case action
when 1 then shares
when 2 then -shares
end) as shares
FROM bf_transactions
GROUP BY symbol
SQL Fiddle here
It is however good practice to denormalize this kind of data - what you appear to have now is a correctly normalized database with no duplicate data, but it's rather impractical to use as you can see in cases like this. You should keep a separate table with current stock portfolio that you update when a transaction is executed.
Also, including a HAVING-clause to 'hide' corrupted data (someone has sold more than they have purchased) seems rather bad practice to me - when a situation like that is detected you should definitely throw some kind of error, or an internal alert.