I have been trying to query the increase percentage of a product grouped in certain range depending on the actual increase for each run. So for example I have the following table schema
Now, if I query the increase percent I would get something like:
SELECT *, (((newPrice - price)/price) * 100 ) as PERCENTAGE FROM Product
What Im trying to obtain is to group the values within a particular range depending on the calculated increase. So for this run something like this:
| Range | #COUNT |
| 0-10% | 3 |
| 30-40% | 1 |
and more ranges and products if existing
I have tried:
Select *, COUNT(idProduct) AS COUNT FROM Product
where (((newPrice - price)/price) * 100 ) BETWEEN 0 AND 10
which gives me:
But I need to configure the query in a way it can determine a reasonable percent range (i.e Without hard coding the values BETWEEN 0 AND 10) and group the values in there for different runs. Any ideas?
Thank you!
product table
CREATE TABLE `product` (
`idproduct` INT NOT NULL ,
`description` VARCHAR(45) NULL ,
`price` INT NULL ,
`newPrice` INT NULL ,
PRIMARY KEY (`idproduct`) );
You could group by 10% percentage bands:
SELECT floor((newPrice - price) / price * 10) * 10 as LowerBound
, floor((newPrice - price) / price * 10) * 10 + 10 as HigherBound
, count(*) as Count
FROM Product
GROUP BY
floor((newPrice - price) / price * 10)
Multiplying by 10 and rounding down should create one group per 10 percentage points.
SELECT
r.RangeValue,
COUNT(*) AS CountofProducts
FROM (SELECT
CASE WHEN (((newPrice - price)/newPrice) * 100 ) <= 10 THEN
'0-10%'
WHEN (((newPrice - price)/newPrice) * 100 ) <= 20 THEN
'10-20%'
WHEN (((newPrice - price)/newPrice) * 100 ) <= 30 THEN
'20-30%'
WHEN (((newPrice - price)/newPrice) * 100 ) <= 40 THEN
'30-40%'
ELSE
'40+%'
END AS RangeValue
FROM Product) r
GROUP BY r.RangeValue
Its simple
SELECT count(*) as items, (((newPrice - price)/newPrice) * 100 ) as PERCENTAGE ,
IF (
((newPrice - price)/newPrice* 100) >=0 &&
((newPrice - price)/newPrice* 100) <=10 ,
"0 - 10%" ,
IF (
((newPrice - price)/newPrice* 100) >=11 &&
((newPrice - price)/newPrice* 100) <=30 ,
"10 - 30%",
so on....
)
) AS 'range'
FROM Product
group by range
Basically, you have to use nested if() statements and inside them you put the ranges.
Then give it a meaningful alias. You can then group by the alias.
Related
I'm running the following query in MySQL:
SELECT (SUM(total) / 100) -
(SELECT (SUM(other_table.total) / 100) FROM other_table WHERE 1) ) AS total
FROM orders WHERE 1
It works as expected if there is at least one row in other_table.
If there are no rows in other_table the result is NULL.
I know this happens because (SUM(other_table.total) gives NULL when there is nothing to SUM.
My question is: How could I update the query to account for the possibility of having an empty other_table
Use COALESCE :
SELECT (SUM(total) / 100) -
COALESCE( (SELECT (SUM(other_table.total) / 100) FROM other_table WHERE 1) ,0) AS total
FROM orders WHERE 1
I am performing an operation to work out a percentage based on 2 values.
I have a single table that tracks an overall value against months and years.
Table Name - donation_tracker
I am comparing across all months across current and previous year then performing a calculation such as:
Current Value (Month- January, Year- 2014, CityID- 1) / Previous Value (Month- January, Year- 2013, CityID- 1) = Division Value * 100 = New Percentage Value.
Some of the math operations appear to be correct but some are incorrect for example the image below is showing 140 when it should be 130.
The values I am quering are as follows:
The column donation_amount is set as
Type = Decimal
Length = 10,2.
Sum should be 130...
SQL CODE-
SELECT city_markers.City_ID, city_markers.City_Name, city_markers.City_Lng, city_markers.City_Lat, SUM( d2.Donation_Amount ) , d1.Month, d1.Year, round( (
D2.Donation_amount / D1.Donation_amount
) *100, 2 )
FROM `city_markers`
INNER JOIN donation_tracker d1 ON city_markers.City_ID = d1.City_ID
INNER JOIN donation_tracker D2 ON d1.month = D2.month
AND d1.month = 'January'
AND d2.month = 'January'
AND d2.year = '2014'
AND D1.year = D2.year -1
AND D1.Location_ID = D2.Location_ID
GROUP BY city_markers.City_ID
Thank you.
You do not sum up the amounts here:
round( (D2.Donation_amount / D1.Donation_amount) *100, 2 )
So the result is calculated by the values of each first row:
round( (70 / 50) *100, 2 ) ==> 140
Use sum() to get the intended result:
round( (sum(D2.Donation_amount) / sum(D1.Donation_amount)) *100, 2 )
I have a table like this:
ID_____StartDate_____EndDate
----------------------------
1______05/01/2012___02/03/2013
2______06/30/2013___07/12/2013
3______02/17/2010___02/17/2013
4______12/10/2012___11/16/2013
I'm trying to get a count of the ID's that were active during each year. If the ID was active for multiple years, it would be counted multiple times. I don't want to "hardcode" years into my query because the data is over many many multiple years. (i.e. can't use CASE YEAR(StartDate) WHEN x then y or IF...
Desired Result from the table above:
YEAR_____COUNT
2010_____1
2011_____1
2012_____3
2013_____4
I've tried:
SELECT COUNT(ID)
FROM table
WHERE (DATE_FORMAT(StartDate, '%Y-%m') BETWEEN '2013-01' AND '2013-12'
OR DATE_FORMAT(EndDate, '%Y-%m') BETWEEN '2013-01' AND '2013-12')
of course this only is for the year 2013. I also tried:
SELECT YEAR(StartDate) AS 'Start Year', YEAR(EndDate) AS 'End Year', COUNT(id)
FROM table
WHERE StartDate IS NOT NULL
GROUP BY YEAR(StartDate);
though this gave me just those that started in a given year.
Assuming that there is an auxiliary table that contains consecutive numbers from 1 .. to X (where X must be grather than possible number of years in the table):
create table series( x int primary key auto_increment );
insert into series( x )
select null from information_schema.tables;
then the query might look like:
SELECT years.year, count(*)
FROM (
SELECT mm.min_year + s.x - 1 as year
FROM (
SELECT min( year( start_date )) min_year,
max( year( end_date )) max_year
FROM tab
) mm
JOIN series s
ON s.x <= mm.max_year - mm.min_year + 1
GROUP BY mm.min_year + s.x - 1
) years
JOIN tab
ON years.year between year( tab.start_date )
and year( tab.end_date )
GROUP BY years.year
;
see a demo: http://www.sqlfiddle.com/#!2/f49ab/14
Why when I have records like (ratings = varchar):
A - 100
B - 70
C - 30
Then:
SELECT * FROM `videos` ORDER BY `rating` DESC
Gives:
A - 30
B - 70
C - 100
And:
SELECT * FROM `videos` ORDER BY `rating` ASC
Gives:
A - 100
B - 70
C - 30
But when the (ratings = tinyint):
SELECT * FROM `videos` ORDER BY `rating` DESC
Gives:
A - 100
B - 70
C - 30
When you have a varchar column, the length of the text data and the fact the char '0' comes before char '1' (rather than after char '9') affects the sort order.
e.g. compare
select '100' as col1
union all
select '70' as col1
order by col1 asc
with
select '100' as col1
union all
select '070' as col1
order by col1 asc
You can get around this by suitably padding all strings to the same length.
you can try:
SELECT * FROM videos ORDER BY rating, videos DESC
I am trying to generate a random integer for each row I select between 1 and 60 as timer.
SELECT downloads.date, products.*, (FLOOR(1 + RAND() * 60)) AS timer
I have searched and keep coming up to this FLOOR function as how to select a random integer in a range. This is giving me a 1 for every row.
What am I missing?
I am on mysql 5.0.75
Heres the rest of the query I belive it might be a nesting issue
SELECT *
FROM (
SELECT downloads.date, products.*, FLOOR(1 + (RAND() * 60)) AS randomtimer,
(
SELECT COUNT( * )
FROM distros
WHERE distros.product_id = products.product_id
) AS distro_count,
(SELECT COUNT(*) FROM downloads WHERE downloads.product_id = products.product_id) AS true_downloads
FROM downloads
INNER JOIN products ON downloads.product_id = downloads.product_id
) AS count_table
WHERE count_table.distro_count > 0
AND count_table.active = 1
ORDER BY count_table.randomtimer , count_table.date DESC LIMIT 10
This is working for me. Your mysql version maybe?
SELECT id, (FLOOR( 1 + RAND( ) *60 )) AS timer
FROM users
LIMIT 0 , 30
The output of the RAND function will always be a value between 0 and 1.
Try this:
SELECT downloads.date, products.*, (CAST(RAND() * 60 AS UNSIGNED) + 1) AS timer
Old question, but always actual problem.
Here a way to create a MySQL function random_integer() based on manual :
CREATE FUNCTION random_integer(value_minimum INT, value_maximum INT)
RETURNS INT
COMMENT 'Gets a random integer between value_minimum and value_maximum, bounds included'
RETURN FLOOR(value_minimum + RAND() * (value_maximum - value_minimum + 1));
SELECT ALL random_integer(1, 60) AS timer;
I'm running your query and it does give me a random number for each row.... maybe has something to do with the name of the random (timer)?
You can increase the number multiplied by the number of records in the table.
SELECT id,
(FLOOR( (SELECT MIN(id) FROM your_table ) + RAND( ) * 1000000 ) ) AS timer
FROM your_table
LIMIT 0 , 30