I am trying to take the average of the values for a category, where the rows are grouped by sub-category with a calculated sum. The Primary key of the Parent Table is the grouped attribute of the Child Table. The grouped attribute of the Parent Table is neither the primary key or in the Child Table.
Simple representation:
select Category, avg(CalculatedSum)
from ParentTable pt
inner join (
select Subcategory, sum(Quantity * Price) as 'CalculatedSum'
from ChildTable
group by Subcategory
) ct
on pt.ID = ct.Subcategory
group by Category
The actual SQL is as follows:
select c.CU_AGE_RANGE, count(*) as '# of Customers', avg(SumSales) as 'Avg of SumSales', max([Max of SumSales]) as 'Max of SumSales', min([Min of SumSales]) as 'Min of SumSales'
from Customers c
inner join (
select CUSTOMER_ID, sum(QTY_SOLD * SALES) as SumSales, max(QTY_SOLD*SALES) as 'Max of SumSales', min(QTY_SOLD*SALES) as 'Min of SumSales'
from Sales
where (SALES > 0) and (QTY_SOLD > 0) and (COST > 0)
Group by CUSTOMER_ID
) s
on c.CUSTOMER_ID = s.CUSTOMER_ID
group by c.CU_AGE_RANGE
I have tried changing the group by clause to various orders of the Category (CU_AGE_RANGE) and Subcategory (CUSTOMER_ID) but am always having the same error.
The error is that the table will always show me the SUM of the SUMS (I believe). I am assuming this is the error because the typical average in the Child Table is 250 to 1000, and the Avg(Sum()) is returning values that are roughly the number of rows per Category times the expected Sum().
I cannot post a photo due to low reputation, so please see the following Comma Delimited Results Table:
CU_AGE_RANGE,#_of_Customers,Avg_of_SumSales,Max_of_SumSales,Min_of_SumSales
NULL,125,4261665.306,433460737.7,0.0017
20-29 ,1192,1154040.907,1374037708,0.00025
30-39 ,1902,25429.52329,29426212.64,0.00015
40-49 ,2118,2418.829874,2066725,0.0001
50-59 ,2204,114625.4111,248240261.3,0.00015
60+ ,2135,160156.4341,334617675,0.0005
patrickbig,1,65.5737,12,0.06
Under 19 ,484,1431.262112,92160,0.0001
I am trying to figure out why the AVG(SUM()) is returning what seems to be the SUM(SUM()). My current hunch is that since the SUM() is of a calculated entry, the calculated value is recalculated based on the grouping in the Parent Table. So this would be:
DESIRED:
x * y for each row in Child Table
sum(x*y) for each Subcategory
Avg(sum(x/y)) for each Category of Subcategory
QTY_SOLD * SALE for each row in Sales
sum(QTY_SOLD*SALE) for each CUSTOMER_ID
avg(sum(QTY_SOLD*SALE) for each CU_AGE_RANGE group of CUSTOMER_IDs
ACTUAL:
x * y for each row in Child Table
sum(x * y) for each Subcategory
avg(sum(x * y) for each Category
avg(sum(QTY_SOLD*SALE) for each CU_AGE_RANGE
which is equal to:
sum(QTY_SOLD*SALE) for each CU_AGE_RANGE
How do I get from the current (sum of Category) to desired (avg by Category of sum of Subcategory)?
Your count of customers is wrong. You are counting the number of sales made, not the number of customers. Change to count( DISTINCT c.CUSTOMER_ID ) should solve it.
select c.CU_AGE_RANGE, count( DISTINCT c.CUSTOMER_ID ) as '# of Customers', avg(SumSales) as 'Avg of SumSales', max([Max of SumSales]) as 'Max of SumSales', min([Min of SumSales]) as 'Min of SumSales'
from Customers c
inner join (
select CUSTOMER_ID, sum(QTY_SOLD * SALES) as SumSales, max(QTY_SOLD*SALES) as 'Max of SumSales', min(QTY_SOLD*SALES) as 'Min of SumSales'
from Sales
where (SALES > 0) and (QTY_SOLD > 0) and (COST > 0)
Group by CUSTOMER_ID
) s
on c.CUSTOMER_ID = s.CUSTOMER_ID
group by c.CU_AGE_RANGE
Let's think about the sub-query first:
select Subcategory, sum(Quantity * Price) as 'CalculatedSum'
from ChildTable
group by Subcategory
Each and every record of the resulting relation is representing an aggregation of a Subcategory. Now, avg(CalculatedSum) should yield the average of the CalculatedSum values. Try to calculate sum(CalculatedSum) instead and see if there is a difference.
Related
first ,i need to get the sum of TotalPrice of sport's and music's departments from the first 3 months of 2016,second, i need to get the result of what i wrote before dividing to sum of all TotalPrice at the year of 2016 from all departments, and third- i need to get the first result dividing to sum of all Total price from all over the years.
all this at the same query!
thanks!
the table called Sales and the attributes are: S_id, date, department, totalPrice.
THIS IS MY CHRY :
Select sum(TotalPrice) as sportMusic, sportMusic/sum(TotalPrice)
From Sales
Where (Department="MUSIC" OR Department="SPORT") and
DATE BETWEEN "2016/01/01" AND "2016/03/31"
You can use your query and two more queries as subqueries (also called "derived tables") in your from clause. Cross join the three result rows and use the totals in your select clause. Something along the lines of:
select
ms_2016_q1.total as ms_2016_q1_total,
ms_2016_q1.total / all_2016.total as rate_2016,
ms_2016_q1.total / all_years.total as rate_all
from
(
select sum(totalprice) as total
from sales
where department in ('MUSIC', 'SPORT')
and date between date '2016-01-01' and date '2016-03-31'
) ms_2016_q1
cross join
(
select sum(totalprice) as total
from sales
where date between date '2016-01-01' and date '2016-12-31'
) all_2016
cross join
(
select sum(totalprice) as total
from sales
) all_years;
I have the following issue:
It is necessary to write a query that will output 'item_id', 'price_in_byr'.
'price_in_byr' is calculated as the 'price' of the items table multiplied by the currency rate at the maximum date of the rate from the table rates.
See Schema
I apologize for my English, I'll try to explain by example:
Goods with item_id = 5 costs 20 euros, in the rates table the maximum date for the euro is January 12, at that date the exchange rate was 25. Total our 'price_in_byr' is 25 * 20 = 500
My solution with temp table:
CREATE TABLE tempRate SELECT currency, MAX(rate) AS maxRate FROM rates GROUP
BY currency;
SELECT items.item_id,(ifnull(tempRate.maxRate,1) * items.price) AS price_in_byr
FROM items
LEFT JOIN tempRate ON items.currency = tempRate.currency;
Tell me please, how can I do it in one query?
You can just use a subquery:
SELECT
items.item_id,(ifnull(tempRate.maxRate,1) * items.price) AS price_in_byr
FROM
items
LEFT JOIN
(
SELECT
currency, MAX(rate) AS maxRate
FROM
rates
GROUP BY
currency
) AS tempRate
ON items.currency = tempRate.currency;
In practice, you substitute "tempRate" by (definition of tempRate) AS tempRate.
You can see an example at dbfiddle here
If you actually want the * most_recent_rate*, you'd do something completely different; insert a subquery to compute it. This subquery looks for all rates of the given currency, sorts them by their exchange_ts (meaning timestamp) in descending order, and just picks to top 1:
SELECT
items.item_id,(ifnull(
(
SELECT
rate AS most_recent_rate
FROM
rates
WHERE
rates.currency = items.currency
ORDER BY
exchange_ts DESC
LIMIT 1
)
, 1) * items.price) AS price_in_byr
FROM
items ;
dbfiddle here
You can make your tempRate query into a subquery:
SELECT
items.item_id,
(ifnull(tempRate.maxRate,1) * items.price) AS price_in_byr
FROM
items
LEFT JOIN (
SELECT currency, MAX(rate) AS maxRate
FROM rates
GROUP BY currency
) as tempRate ON items.currency = tempRate.currency;
I am not sure if mysql supports this level of subquery but see if it works:
select I.item_id, I.price * CR.rt
from
items as I,
(
select r.currency cy, r.rate rt
from
rates as r, (select currency, max(date) max_date from rates group by currency) as R_MAXDATES
where
r.currency = R_MAXDATES.currency
and r.date = R_MAXDATES.max_date;
) As CR
where
I.currency = CR.cy
I have a reasonably complex query, that I've simplified down here to try and make it understandable.
In the example below, I am trying to obtain a SUM of sales for two different products. When I retrieve the SUMs individually, as per the first two columns, they calculate correctly.
However, when adding the two SUM queries together (in the third column), if product Y has been sold but NOT product X, the value returns as completely blank.
Any ideas why this might be?
SELECT
(
SELECT SUM(IFNULL(product_x_sales.price, 0))
FROM sales AS product_x_sales
GROUP BY product_x_sales.customer_id
) AS "Total Sales of Product X",
SUM(IFNULL(product_y_sales.price, 0)) AS "Total Sales of Product Y",
(
SELECT SUM(IFNULL(product_x_sales.price, 0))
FROM sales AS product_x_sales
GROUP BY product_x_sales.customer_id
) + (
SUM(IFNULL(product_y_sales.price, 0))
) AS "Total Sales of Products X and Y"
FROM customers
JOIN sales AS product_y_sales ON customers.id = product_y_sales.customer_id
GROUP BY agents.id
When X has no sales, the result of your select would be NULL.
Adding NULL to sales of Y will result in NULL.
SELECT SUM(IFNULL(product_x_sales.price, 0)) <-- = NULL
Change it to this instead
SELECT IFNULL(SUM(IFNULL(product_x_sales.price, 0)), 0)
I think I'm missing a simple step here but I can't seem to figure it out. I've read the other threads and they talk about grouping but I can't seem to put it all together right.
I have a simple table that holds inventory transactions. In each row, there is a quantity and a price. I want to get the sum of the quantity and the sum of the each price * each quantity.
Here's my query. If I remove the grouping, I get 1 result that is multiplied by the number of rows in the table. If I add the grouping, I get the correct result multiple times. Am I missing something here? I just feel like running a query to get 20k results when they all contain the same data would be pointless.
SELECT (SUM(i.quantity) - IFNULL(SUM(s.quantity), 0)) AS quantity,
SUM(i.unitprice * i.quantity) AS totalprice
FROM 02_01_transactions t
LEFT JOIN 02_01_transactions i
ON i.type = 1
AND i.active = 1
LEFT JOIN 02_01_transactions s
ON s.type = 2
AND s.active =1
GROUP BY t.id
Not sure there is a need for the joins (you are not joining on any common value) or the type = 2 rows if you are just subtracting them out. Is there a reason the following does not work?
-- Total quantity, total price of all type 1, active transactions.
SELECT SUM(quantity) AS quantity,
SUM(unitprice * quantity) AS totalprice
FROM 02_01_transactions
WHERE type = 1
AND active = 1
Here's my guess at what you were trying to accomplish:
select
sum(quantity * case type when 1 then 1 when 2 then -1 end) as quantity,
sum(unitprice * quantity) as totalprice
from 02_01_transactions
where type in (1, 2) and active = 1
I have a table in MySql related to purchase of Inventory.
The table format is as below :
itemname (varchar)
vendor (varchar)
pdate (datetime)
qty (decimal)
rate (decimal)
total (decimal)
id (mediumint) (autoincrement)
A report is to be generated that must have the following columns
Item HighestRate HighestRateDate LowestRate LowestRateDate % difference
--
Item is the itemname
HighestRate and HighestRateDate are rates at maximum
LowestRate and Date are rates at minimum
%difference is a basic difference percentage between highestrate and lowestrate of a row
I have prepared the following query
SELECT itemname,rate,pdate from purchases
group by itemname
having rate = max(rate)
order by itemname
which does generate one half of the report.
However since it requires both the lowest and highest rate. This report is incomplete and printing two reports makes comparison difficult.
Any help would be appreciated.
Thankyou
Here goes. It's not pretty but it works.
select min.itemname,
min.rate,
min.pdate,
max.rate,
max.pdate,
(max.rate - min.rate)/max.rate as diff
from (SELECT p.itemname,
p.rate,
pdate
from purchases p,
(select itemname,
max(rate) as rate
from purchases
group by itemname) max_values
where p.itemname = max_values.itemname
and p.rate = max_values.rate
) max,
(SELECT p.itemname,
p.rate,
pdate
from purchases p,
(select itemname,
min(rate) as rate
from purchases
group by itemname) min_values
where p.itemname = min_values.itemname
and p.rate = min_values.rate
) min
where max.itemname = min.itemname;
You'll need an index on (itemname, rate) for this query not to be awfully slow.
If there are two or more dates with same maximum (or minimum) rate, then a (more or less) random date will be selected. If you want to control that, change the ORDER BY rate ASC (to ORDER BY rate ASC, pdate DESC for example):
SELECT
di.itemname AS Item
, maxr.rate AS HighestRate
, maxr.pdate AS HighestRateDate
, minr.rate AS LowestRate
, minr.pdate AS LowestRateDate
, (maxr.rate - minr.rate)/maxr.rate --- calculations
AS PrecentDifference
FROM
( SELECT DISTINCT itemname
FROM purchases
) AS di
JOIN
purchases AS minr
ON minr.id = --- I guess this is the PK
( SELECT id
FROM purchases p
WHERE p.itemname = di.itemname
ORDER BY rate ASC
LIMIT 1
)
JOIN
purchases AS maxr
ON maxr.id =
( SELECT id
FROM purchases p
WHERE p.itemname = di.itemname
ORDER BY rate DESC
LIMIT 1
)