SQL group by - merge groups - mysql

Is it possible to "merge" 2 groups obtained after a SQL statement that use group by. For example if I have a field size ENUM('extra-small, 'small', 'medium', 'large', extra-large') and then I run this query SELECT * from clothes GROUP BY size;, but for in one case I would like to get in result "extra-small" and "small" in the same group. Is this possible with SQL?

yes, you can:
select count(*)
, case size
when 'extra-large'
then 'large'
else size end as grouped_size
from sizes
group by grouped_size
demo: http://sqlfiddle.com/#!2/ae3fa/2

How about using MySQL GROUP_CONCAT(expr)
This function returns a string result with the concatenated non-NULL
values from a group. It returns NULL if there are no non-NULL values.
Also have a look at MySQL – The GROUP_CONCAT() function

Related

Replace null with zero in sql query

I have an sql query that could potentially return null values, in the event of this I want the query to return '0'. Here is the query
SELECT (select count(goal) from fixtures where goal='1' and fixture='$fixture') as goalCountHome
from fixtures where fixture='$fixture'LIMIT 1
Any help much appreciated!
In MySql use IFNULL() function. For MsSql use ISNULL() function.
If you are using MySql, IFNULL(<column_name>, 0) should do.
This query:
SELECT (select count(goal) from fixtures where goal='1' and fixture='$fixture') as goalCountHome
FROM fixtures
WHERE fixture = '$fixture'
LIMIT 1
cannot return NULL values. The subquery is an aggregation query with no GROUP BY, so it always returns one row. That row will contain a result from COUNT(). COUNT() itself can never return a NULL value. If there are no rows, then the value will be zero.
The outer query might return no rows but that is different from NULL values.
Of course, this query is way overcomplicated, and should simply be:
SELECT COUNT(*) as goalCountHome
FROM fixtures
WHERE fixture = ? AND -- pass this in as a parameter
goal = 1 ; -- it looks like a number so I assume it is
Note that you should be passing parameters in using proper parameters rather than munging query strings.
if you need all the rows and not the rows where goal is not null you could use count(*)
select count(*)
from fixtures
where goal=1
and fixture='$fixture'
count(goal) return the number of rows where goal is not null
count(*) return the total number rows selected
otherwise in general when you need not null values in mysql you can ifnull(your_column, value) or coalesce(your_column, value)
based on you comment seems you need sum(goal)
select sum(ifnull(goal,0))
from fixtures
where goal=1
and fixture='$fixture'

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

NULL to zero with ISNULL

I have the following SQL statement:
SELECT name, SUM(growth) AS sum_buy_price, SUM(recovery) AS sum_msrp, SUM(growth)+SUM(recovery) AS total
FROM orders
WHERE id = ?
GROUP BY name
My data is coming from a CSV file that I have no control over and either 'growth' or 'recovery' can be NULL in the data, but not at the same time. I need to use ISNULL to convert the possible NULL values to zero in order for the SUM to work correctly, but I'm unsure of how/where to add the ISNULL since the SELECT is indexing another record (name).
ISNULL returns whether the argument passed is null (i.e., it is analogous to true or false). I suppose, what you need is IFNULL:
SELECT
name,
SUM(IFNULL(growth, 0)) AS sum_buy_price,
SUM(IFNULL(recovery, 0)) AS sum_msrp,
SUM(IFNULL(growth, 0))+SUM(IFNULL(recovery,0)) AS total
FROM
orders
WHERE
id = ?
GROUP BY
name
The SUM() function ignores NULL values, so you don't need to change a NULL to a 0 in order for it to work properly.
If however, all values that you're aggregating are NULL and you want to return a 0 instead of NULL you can use IFNULL() or the more common COALESCE() to show 0 as the sum instead of NULL:
SELECT COALESCE(SUM(growth),0)
ISNULL() is a valid SQL Server function, IFNULL() is the equivalent in MySQL, but all major databases make use of COALESCE() which returns the first non-NULL value in a set, ie: COALESCE(NULL,NULL,5) would return 5.
This should work for you:
SELECT name, SUM(ISNULL(growth, 0)) AS sum_buy_price,
SUM(ISNULL(recovery, 0)) AS sum_msrp,
SUM(ISNULL(growth, 0))+SUM(ISNULL(recovery,0)) AS total
FROM orders
WHERE id = ?
GROUP BY name

mysql avg on conditional

is it possible to get the average value for a column, as well as the average value for the same column with a conditional? or simply to combine these two queries into one.
SELECT AVG( field ) from table
SELECT AVG ( field ) from table where col = some_val
If there isn't a simple way to combine them using native mysql functions, would a stored function be able to handle it, or a user defined function?
Taking advantage of the fact that null values are not included in aggregate functions, we can use a CASE statement to control the average, as in the following:
select avg(amt) as average,
avg(case when col=some_val then amt else null end) as conditionalAverage
from myTable;
Sample Demo: http://sqlize.com/2IXwbWD2Eb
There is another way, not using case when
select
avg(amt) as average,
avg(if(col=some_val,amt,null)) as conditionalAverage
from myTable

MySQL COUNT() and nulls

Am I correct in saying:
COUNT(expr)
WHERE expr IS NOT *
Will count only non nulls?
Will COUNT(*) always count all rows? And What if all columns are null?
Correct. COUNT(*) is all rows in the table, COUNT(Expression) is where the expression is non-null only.
If all columns are NULL (which indicates you don't have a primary key, so this shouldn't happen in a normalized database) COUNT(*) still returns all of the rows inserted. Just don't do that.
You can think of the * symbol as meaning "in the table" and not "in any column".
This is covered in the MySQL Reference Manual.
If you want to count NULLs as well, try
SELECT COUNT(IFNULL(col, 1)) FROM table;
just checked:
select count(*)
returns 1 with one record filled with NULLs
select count(field)
returns 0.
I don't see the point in the record with NULL values. Such record must not exist.
count(*) is not for non-null columns, it's just the way to ask to count all rows. Roughly equivalent to count(1).
Using MySQL I found this simple way:
SELECT count(ifnull(col,1)) FROM table WHERE col IS NULL;
This way will not work:
SELECT count(col) FROM table WHERE col IS NULL;
If you want to count only the nulls you can also use COUNT() with IF.
Example:
select count(*) as allRows, count(if(nullableField is null, 1, NULL)) as missing from myTable;
You can change the if condiditon to count what you actually want. So you can have multiple counts in one query.
select count(*) as 'total', sum(if(columna is null, 1, 0)) as 'nulos' from tabla;