SQL stament groups rows and calculate average - mysql

I am stuck with the following issue. I have 1 table that looks like this:
field_number.. Value
````````````````````````````````
1 ......................... 1
2 ..........................1
3 ......................... 2
4 ..........................2
etc.
I want to group different fieldnumbers and have an average for the value column. So the output should be:
field_number................Value
name(1,2)...................... 1.............. ((1+1)/2)
name(3,4)...................... 2.............. ((2+2)/2)
I have checked previous questions but cannot find any question that covers this issue (I might search on the wrong keywords though). So if this has already been covered my appologies, but any help or a point to a previous answer would be appreciated.
** =============UPDATE============= **
I went through your suggestions but did not get it right. So I am trying to be more specific. I almost have the result I want apart from the fact I want to have a fixed value in one of my columns. I have the following query:
Select
Avg(wp_rg_lead_detail.value),
wp_rg_lead_detail.field_number,
From
wp_rg_lead_detail
Where
wp_rg_lead_detail.field_number In (15, 17, 24) A
UNION
Select
Avg(wp_rg_lead_detail.value),
wp_rg_lead_detail.field_number,
From
wp_rg_lead_detail
Where
wp_rg_lead_detail.field_number In (16, 108, 18)
etc.
This gives me a table with two columns
wp_rg_lead_detail.value................field_number
4.3 (average)..............................15 (first value of av calculation)
What I want is to change the field number (15 in this case) in a fixed value (text). What and how should I add this to the query?

SELECT avg(value) FROM table WHERE field_number in (1,2)
SELECT avg(value) FROM table WHERE field_number in (3,4)

If your table is really this simple, you can also get away with:
select distinct
Value,
count(Value) as '#'
from table_name
group by Value
If you acctually want to group by a range, than you can put the logic of the range in your grouping clause (see this fiddle)
select distinct
avg(Value) as average,
floor(Value),
count(Value) as '#'
from table_name
group by floor(Value)
In the fiddle I used grouping on whole integers, but you can make that as complex as you like (see, for instance, this example)
If you are actually also interested in your corresponding fields, use group_concat() like so
select
Value,
group_concat(
distinct field_number
order by Value
) as fields
from table_name tn1
group by Value
order by Value
output:
Value | fields
---------------------------------
1 | 1,2
2 | 3,4
See this fiddle implemented from this blog post

For a generalized answer.
SELECT CONCAT('name','(',GROUP_CONCAT(field_number),')') AS field_number,
AVG(Value) as Value
FROM table_name
group by table_name.`Value`
Hope this helps.

Related

Finding LEAST/GREATEST values from combined COLUMNS, ignore 0 & NULL- MYSQL

I've got a dataset with a bunch of rows for monthly salary payments for each account. we have 6 columns for this -
Salary_1, Salary_2, Salary_3, Salary_4, Salary_5 and Salary_6.
Sometimes salaries 3, 4, 5, 6 and occasionally 2 aren't populated, sometimes none are populated because they're unemployed. In this case, we have 0 in the field.
What I need to do is combine all salaries and find the MAX and MIN from these columns ---
Select
Greatest(Salary_1, Salary_2, Salary_3, Salary_4, Salary_5, Salary_6) as MaxSal,
Least(COALESCE(Salary_1, Salary_2, Salary_3, Salary_4, Salary_5, Salary_6),0) as MinSal
from
(select
sal1 as Salary_1, Select sal2 as Salary_2, Sal3 as Salary_3, sal4 as Salary_4, Sal5 as Salary_5, Sal6 as Salary_6
from ....)a
The problem is, this is returning the correct value for Max Sal but 0.00 for Min, because it is the minimum value but won't let me ignore 0s, but in this case 0 is not a minimum salary value I want, I need the second lowest value here.
I've tried setting the original Sal1-Sal6 values to NULLIF 0 and it returns NULL for max and 0 for Min.
What else could I have a look at? the COALESCE combined with NULLIF has not worked for me which is what has been recommended on previous questions. Thanks!
Greatest and Least do not ignore nulls like aggregation functions do; you'll need to do something to avoid them. One option is something like this:
Greatest(IFNULL(Salary_1 ,0), ...)
Least(
CASE WHEN Salary_1 IS NULL OR Salary_1 = 0 THEN /*some huge value*/ ELSE Salary_1 END
, CASE WHEN Salary_2
....)
This might be simplest to unpivot and aggregate the data:
select id, max(salary), min(salary)
from ((select id, salary_1 as salary from t) union all
(select id, salary_2 as salary from t) union all
. . .
) t
group by id;
This is definitely more expensive than a giant case expression. On the other hand, it is less prone to error.
The real suggestion is to fix your data model. Trying to store an array in multiple columns is generally a sign of a poor data model. The more appropriate method would have one row per salary rather than putting them in separate columns.

MySQL MAX from count query

I have table rozpis_riesitelov which contains columns :
id_rozpisu_riesit, id_zam, id_projektu, id_ulohy.
I made query :
select id_zam, id_ulohy, count(*) as counted
from rozpis_riesitelov
group by id_zam
having id_ulohy in (1,2,8)
which shows me id of employee (id_zam) and how many times He was in project (id_ulohy is irrevelant but I had to select it beacuse of having clause). It shows me everyone in db but I am looking for employee with ID of 4 who is in 6 projects (Yes, I could do order by but I want to see max). When I do max of this query like this:
select max(counted)
from (select id_zam, id_ulohy, count(id_zam) as counted
from rozpis_riesitelov
group by id_zam
having id_ulohy in (1,2,8)) as riesitel
which shows me number 149 instead of 6.
So basically I only need to find employee that occurs in the most of the projects.
What's wrong with sorting by the COUNT() value, and limiting to one result?
SELECT `id_zam`,
`id_ulohy`,
COUNT(*) AS `counted`
FROM `rozpis_riesitelov `
WHERE `id_ulohy` IN ( 1, 2, 8 )
GROUP BY `id_zam`
ORDER BY `counted` DESC
LIMIT 1
Not sure exactly what you are trying to accomplish but you only use HAVING to filter on your aggregate like this:
HAVING COUNT(*) > 1
you should be able to move the condition to a WHERE clause and get correct max returned:
select max(counted)
from (select id_zam, count(id_zam) as counted
from rozpis_riesitelov
where id_ulohy in (1,2,8)
group by id_zam) as riesitel

WHERE clause in SSRS expression for max function

I have for example a query with return something as it
route value
1 3
2 2
3 4
4 5
5 1
then I need to put in 2 textbox the max and the min route so in sql this would be
select top 1 route from table where value=(select max(value) from table)
I add a image done in excel, how this would be.
I believe this is so easy but I dont have idea how to get it.
I got using expression, this was extactly expression
="Route "+
Convert.ToString (
Lookup(max(fields!value.Value),fields!value.Value ,fields!route.Value,"mydataset")
)
changing max for min, for the other...
thanks everyone.
I believe the query you're looking for would be:
With Min_Max_CTE as (
Select MIN(value) as Min_Value
, MAX(value) as Max_Value
From Table
)
Select Top 1 'Min' as Type
, T.route
, T.value
From Table T
Inner Join Min_Max_CTE CTE
on T.value = CTE.Min_Value
Union All
Select Top 1 'Max' as Type
, T.route
, T.value
From Table T
Inner Join Min_Max_CTE CTE
on T.value = CTE.Max_Value
Order by Type desc --This will put the Min Route first followed by the Max Route
Then, put that query into a dataset, and then create a tablix and use the Type, route, and value fields to return the minimum route and the maximum route. It should end up being set up just like your excel section with the min and max routes above.
You can do this SSRS by using a couple of separate tables. Your example data:
And two tables in the Designer:
Since the tables only have header rows, only the first row in the table will be displayed.
To make sure we get the MAX and MIN values in the two tables, each table needs to order its Dataset appropriately, i.e. by Value by descending and ascending respectively.
MAX table:
MIN table:
Which gives your expected result:

MySQL COUNT() on groups returns wrong number of rows

I have this table called "values":
value
12
13
5
56
3
56
79
98
58
74
52
2
8
32
4
I want to get the lowest value for each block of 5, so I tried this query:
SET #a = -1;
SELECT FLOOR((#a:=#a+1)/5) AS block, MIN(value)
FROM values
GROUP BY block
It seems like this query does not include the last row in each block, so I tried count:
SET #a = -1;
SELECT FLOOR((#a:=#a+1)/5) AS block, COUNT(value)
FROM values
GROUP BY block
which returned:
block COUNT(value)
0 4
1 4
2 4
what is happening here?
Try this:
SELECT FLOOR(id/5) AS block, MIN(`value`)
FROM (SELECT (#id:=#id+1) AS id, `value`
FROM `values`, (SELECT #id:=-1) AS A) AS B
GROUP BY block;
Here is a snippet from the MySQL 5.7 documentation that should help:
In a SELECT statement, each select expression is evaluated only when sent to the client. This means that in a HAVING, GROUP BY, or ORDER BY clause, referring to a variable that is assigned a value in the select expression list does not work as expected:
mysql> SELECT (#aa:=id) AS a, (#aa+3) AS b FROM tbl_name HAVING b=5;
The reference to b in the HAVING clause refers to an alias for an expression in the select list that uses #aa. This does not work as expected: #aa contains the value of id from the previous selected row, not from the current row.
Your query uses block as the expression in the GROUP_BY clause, where block is the result of an assignment, so your situation is the analogous to the one from the MySQL documentation. It certainly looks promising, given that you are "off by one"!
Running an explain might tell you exactly what is happening; it will probably be a good exercise to try this.

SUM of difference in values

I need to query in MS Access the difference in value of a column to 8 and only if it is greater than 8.
So if I have a column of numbers 1-10, I want to query the sum of all the value's differences from 8. So the result of the query for the below column would be 3. (9-8)+(10-8)
SELECT Sum(([time1]-8)+([time2]-8)+([time3]-8)+([time4]-8)+([time5]-8)+([time6]-8)+([time7]-8)+([time8]-8)+([time9]-8)+([time10]-8)+([time11]-8)+([time12]-8)+([time13]-8)+([time14]-8)+([time15]-8)+([time16]-8)+([time17]-8)+([time18]-8)+([time19]-8)+([time20]-8)+([time21]-8)+([time22]-8)) AS Total
FROM tblTimeTracking
WHERE (((Month(([Day])))=Month(Now()))) AND ([time1]>8 AND[time2]>8 AND[time3]>8 AND[time4]>8 AND[time5]>8 AND[time6]>8 AND[time7]>8 AND[time8]>8 AND[time9]>8 AND[time10]>8 AND[time11]>8 AND[time12]>8 AND[time13]>8 AND[time14]>8 AND[time15]>8 AND[time16]>8 AND[time17]>8 AND[time18]>8 AND[time19]>8 AND[time20]>8 AND[time21]>8 AND[time22]) ;
Thanks,
How about:
SELECT Sum([Value]-8) As SumOfVal
FROM table
WHERE [Value]>8
Edit re complete change in original question.
It is not clear what you want
SELECT Sum(([time1]-8)+([time2]-8) ...
WHERE [time1]>8 And Time2>8 ...
Time1>8 will exclude nulls, but if that is not what you are doing, you will need to consider:
Nz([time1],0) + ...
Edit re comments
Something like:
SELECT Sum(times) FROM
(SELECT IIf(Time1>8,Time1-8,Time1) As times FROM Table
UNION ALL
SELECT IIf(Time2>8,Time2-8,Time2) As times FROM Table) As b
As b is an alias: Access SQL
UNION / UNION ALL: View a unified result from multiple queries with a union query