mysql using select with an arithmetic expression - mysql

I am trying to use select in combination with an arithmetic expression
SELECT * FROM `mytable` ORDER BY (`column1` / max(`column1`)* `column2`);
The problem is that it return a single row rather than all the rows sorted base on the expression.
Any idea?

Just order by column1. Dividing by a constant doesn't change the order.
EDIT: Add your expression as another field in the select. E.g.,
SELECT *, x+y as z ORDER BY z
See https://stackoverflow.com/a/10762333/2877364 for a full example of a similar situation.

Related

MySQL select value range within a value range, from a dash-separated column value?

How do I select a value range from a column where two values in it are separated by a dash, using MySQL?
Here's my example table named "example":
The user enters a low value (X) and a high value (Y).
For example X=2.5 and Y=7.2
I want to select all items where the left value is higher than X (in this case 2.5) and the right value is lower than Y (in this case 7.2). Using these X and Y values I should end up with the rows 2 and 5 as a result.
Sort of like this:
SELECT * FROM example WHERE MIN(value) > X AND MAX(value) < Y
How do I do this?
You can use LEFT and RIGHT functions to get X and Y out of your value field.
So I think you are looking for something like this:
SELECT * FROM example WHERE CAST(LEFT(value,3)AS DECIMAL(2,1)) > 2.5 and CAST(RIGHT(value,3)AS DECIMAL(2,1)) < 7.2
First you need to access your table in a fashion that only has one value per column. (Multiple values per column, like 3.5-7.5 happen to be a very common relational database design antipattern. They cripple both performance and clarity.)
This SQL subquery does the trick for pairs of values.
SELECT item_id, name,
0.0+SUBSTRING_INDEX(value, '-',1) first,
0.0+SUBSTRING_INDEX(value, '-', -1) last
FROM example;
The expression 0.0+something is a MySQL trick to coerce a value to be numeric.
Then use the subquery to apply your search criteria.
SELECT item_id, name, first, last
FROM ( SELECT item_id, name,
0.0+SUBSTRING_INDEX(value, '-',1) first,
0.0+SUBSTRING_INDEX(value, '-', -1) last
FROM example
) s
WHERE first > 2.5
AND last < 7.2;
Fiddle here.
In a comment you asked about the situation where you have more than two values in a single column separated by delimiters. See this. Split comma separated values in MySQL
Pro tip Don't put more than one number in a column in an RDBMS table. The next person to use the table will be muttering curses all day while trying to use that data.
Pro tip Use numeric data types, not VARCHAR(), for numbers.

Avoiding redundant expressions in SELECT query

Is there any way to avoid repeating column expressions in the SELECT query? I want to divide the sum and count of a column but would like to use the assigned name instead of repeating SUM(value)/COUNT(value) or using a sub query. Is this possible? If so, does that speed up the query by not repeating the calculation of the sum and count or does mysql remember already calculated expressions?
SELECT datalist.type, SUM(value) AS type_sum, COUNT(value) AS type_count, type_sum/type_count
FROM (...) AS datalist
GROUP BY datalist.type
throws: #1054 - Unknown column 'type_sum' in field list
Unless you put it in outer query, this is the only way.
SELECT datalist.type, SUM(value) AS type_sum, COUNT(value) AS type_count, SUM(value)/COUNT(value)
FROM (...) AS datalist
GROUP BY datalist.type
One workaround would be to use a alias table with pre-defined calculations and then later call it from outer table such as:
select d.type_sum/d.type_count as dividedValue from (SELECT datalist.type, SUM(value)
AS type_sum, COUNT(value) AS type_count
FROM (...) )AS d
GROUP BY d.type

How can I use column relative position in if statement in order by?

I run a SQL query like below in MySQL:
select *
from (
select 2 as o,1 as t from dual
union
select 1 as o,2 as t from dual
) x
order by if((select 1),o,t);
It works well, but when I use column relative position in if statement, it doesn't work.
How can I use column relative position in if in ORDER BY statement?
select *
from (
select 2 as o,1 as t from dual
union
select 1 as o,2 as t from dual
) x
order by if((select 0),1,2);
I'm not sure what your real confusion is. When an integer appears in an order by, then this is treated as a column number. Any other use of an integer is interpreted as an expression.
The use of column numbers has been removed from the SQL standard. Hence, its use in any particular database is not guaranteed in future releases. It is really better to use the column names.
I think you want to sort your query based on a criteria over two columns, if I'm correct, you can use something like this:
...
order by
case when (your criteria)
then column1
else column2
end;
Note: use union all instead union when you don't want to remove duplicate values as performance issue ;).

mysql calculate percentage for diffrent groups

I want to calculate percentage for test groups.
I have group A,B and C. And I want to know how much success percentage each group have.
My first query is counting total test ran in each group by doing the following:
SELECT type, count(type) as total_runs
From mytable
Where ran_at > '2015-09-11'
Group by type
Second query is counting success for each group:
SELECT type, count(type) as success
FROM mytable
where run_status like '%success%' and ran_at> '2015-09-11'
Group by type
Now I need to divide one in the other and multiply in 100.
how do I do this in one query in an efficient way, I guess nested query is not so efficient- but anyway I can't see how I can uses nested query to solve it.
I would appreciate answer which include simple way, maybe not so efficient, and an efficient way with explanations
You can just use conditional aggregation:
SELECT type, sum(run_status like '%success%') as success,
100 * avg(run_status like '%success%') as p_success
FROM mytable
where ran_at> '2015-09-11'
Group by type;
In a numeric context, MySQL treats boolean expressions as integers with 1 for true and 0 for false. The above works assuming that run_status is not NULL. If it can be NULL, then you need an explicit case statement for the avg().
I had this one, but Gordon have a better solution if run_status is not NULL.
Select type, sum(if(run_status like '%success%',1,0)) / count(1) * 100) as p_success
From mytable
Where ran_at > '2015-09-11'
Group by type

SQL - Rounding decimals from a count sum without a column

How can I round the decimals from a count sum without having a column. A column is required in the use of ROUND(), so I am clueless. I'm trying not to create any more columns.
Here is what I have done so far and which works, but it displays too many decimals (4 after the zero). Please note that the reason that the SELECT phrase is in brackets is because it's in another SELECT phrase). What matters is that my code works, but I can't get rid of the decimals...
(SELECT (COUNT(v.id) * r.res_cpm/1000)
FROM databasename_viewcounter v
WHERE v.subject_id = r.subject_id) AS cpm_revenue
FROM databasename_resources r
WHERE r.order_id=:order_id
ORDER BY r.beginning ASC");
The following function CASTS the select statement as decimal
cast((COUNT(v.id) * r.res_cpm/1000)as decimal (10,2))