How to select median value? [duplicate] - mysql

This question already has answers here:
Simple way to calculate median with MySQL
(48 answers)
Closed 4 years ago.
Could anybody give me a hint how to find median value for "tax" during 12.04.18 - 16.04.18:
user_id login_time tax
3 2018-04-15 16625000
5 2018-04-16
6 2018-04-17 296470000
6 2018-04-16 192519750
6 2018-04-15 4455500
6 2018-04-13 17125
6 2018-04-12 120180000
7 2018-04-18 24060000
7 2018-04-17 42959500
The result equals 16625000 (because there is NULL value. We need to use it as 0).
Thank U for attention to my question!

The median is the value
located exactly in the middle of an odd dataset.
Or the average of the two middle values in an even dataset.
So, by considering this two cases, the first you need is the count of datarows. Then, you have to decide (simple case) if you pick the value in the middle, or if you need the average of two values (Don't forget to apply sorting prior to selecting the actual values):
I would use a little "code" to achieve this:
Pseudo-Code:
1.) SELECT count(id) AS val FROM myTable WHERE datetime ... //$val=9
2.) Programming language: $lim = floor($val/2); // $lim=4
if odd($val){
3.) SELECT tax FROM myTable WHERE datetime [...] ORDER BY tax LIMIT $lim,1
}
else if even($val){
3.) Programming language: $lim -=1; // if $val was 10, we want row 4 and 5
4.) SELECT AVG(tax) AS tax FROM
(SELECT * FROM myTable WHERE datetime [...] ORDER BY tax LIMIT $lim,2) AS tmp
}
[...]
echo "Median is: ". $row["tax"];

Related

SQL Query - For Count of Records [duplicate]

This question already has an answer here:
Find total count based of values from another table
(1 answer)
Closed 2 years ago.
I've one table named "history" (Column Names are: ID, Records, Stage, Date) where I've the following records:
1 Record1 Stage1 Date
2 Record2 Stage1 Date
3 Record3 Stage1 Date
4 Record1 Stage2 Date
all that Records having some priority saved in master table named as "Records" (Column names are: id, Record, Stagename, date) like as shown below
1 Record1 High Date
2 Record2 Low Date
3 Record3 Medium Date
upto more than 100+ records
So i want to show the COUNT of High Low and Medium
Desired Output:
[#] For Stage 1
High - 1
Low - 1
Medium -1
[#] For Stage 2
High - 1
Low - 0
Medium - 0
Could you please help me into this?
Here what my code is:
$stagename = "Stage 1";
$query= $conn->prepare("SELECT count(*) FROM history WHERE stagename=?");
$stmt->execute(array($getstagename));
$count= $stmt->fetchColumn();
I'm guessing the column names (since you didn't include them), but the query should go like this:
select
h.stage,
r.priority,
count(*)
from history h
join records r on r.record_name = h.record_name
group by h.stage, r.priority
order by h.stage, r.priority

select highest value in mysql [duplicate]

This question already has answers here:
Select max value of each group
(8 answers)
How to select a maximum value row in mysql table
(7 answers)
Closed 4 years ago.
So I have a database that has some values like this:
Level , Indicator
4 1
3 2
4 3
3 4
4 5
3 6
What I want to do is to select the highest level value in every indicator.
Is there any sql query that I can use that will generate a result like this?
Level , Indicator
4 1
4 3
4 5
If not, can you help me out using php and mysqli? Thank you so much.
To get Indicators having just highest level value -
select distinct Indicator, level
from your_table
where level = (select max(level) from your_table)
Also, you can use group by to get highest level for each Indicator value -
select Indicator, max(Level) from your_table group by Indicator

MySQL query several records from certain date range [duplicate]

This question already has answers here:
What is the most straightforward way to pad empty dates in sql results (on either mysql or perl end)?
(9 answers)
Closed 6 years ago.
here's my recordset:
id date
-----------------------
1 2017-01-11
2 2017-01-12
3 2017-01-14
4 2017-01-15
4 2017-01-16
i'd like to query all records within the date range 2017-01-14 to 2017-01-16
currently i'm using:
SELECT * FROM foo WHERE (date='2017-01-14' OR date='2017-01-15' OR date='2017-01-16')
is there a better way (which would be probably faster for bigger ranges)?
thanks
PS: i'm aware i could use:
SELECT * FROM foo WHERE date >= '2017-01-14' AND date <= '2017-01-16'
but the problem is that i don't want "gaps" between each day.
SELECT *
FROM foo
WHERE date BETWEEN '2017-01-14' AND '2017-01-16';

MySQL GROUP BY DateTime with Aggregate Function [duplicate]

This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 7 years ago.
I seem to remember this working as expected in Oracle, but I can't figure out how to get it right in MySQL.
Here is my query:
SELECT DateTimeStamp, MAX(Value) FROM t1
GROUP BY YEAR(DateTimeStamp), MONTH(DateTimeStamp), DAY(DateTimeStamp);
Running this produces results like:
DateTimeStamp Value
2015-09-09 00:00:29 100
2015-09-10 00:00:05 58
2015-09-11 00:00:57 62
2015-09-12 00:00:49 69
2015-09-13 00:00:43 97
But I was expecting it to look like this, where the DateTimeStamps match up with the values:
DateTimeStamp Value
2015-09-09 03:28:29 100
2015-09-10 03:29:05 58
2015-09-11 03:31:57 62
2015-09-12 03:30:49 69
2015-09-13 03:28:43 97
The correct maximum values are being selected, but the matching DateTimeStamps for those maximum values are not. Instead, it looks like the first DateTimeStamp value for each day is being selected. How can I change my query to display the matching DateTimeStamps?
If all you need is to strip the time section, you need to use the date function:
SELECT date(DateTimeStamp) AS DateTimeStamp, MAX(Value) AS MaxValue
FROM t1
GROUP BY date(DateTimeStamp);
Note: Grouping by something usually make sense when you select it. There is no point to group by YEAR(DateTimeStamp), MONTH(DateTimeStamp), DAY(DateTimeStamp) if all you need is the maximum value per each day.

MySQL: Matching inexact values using "ON"

I'm way out of my league here...
I have a mapping table (table1) to assign particular values (value) to a whole number (map_nu). My second table (table2), is a collection of averages (avg) for each user (user_id).
(I couldn't figure out how to properly make a markdown table, please feel free to edit!)
table1: table2:
(value)(Map_nu) (user_id)(avg)
---- -----
1 1 1 1.111
1.045 2 2 1.2
1.09 3 3 1.33333
1.135 4 4 1
1.18 5 5 1.389
1.225 6 6 1.42
1.27 7 7 1.07
1.315 8
1.36 9
1.405 10
The value Map_nu is a special number that each user gets assigned according to their average. I need to find a way to match the averages from table2 to the closest value in table1. I only need to match to the 2 digit past the decimal, so I've added the Truncated function
SELECT table2.user_id, map_nu
FROM `table1`
JOIN table2 ON TRUNCATE(table1.value,2)=TRUNCATE(table2.avg,2)
I still miss the values that don't match the averages exactly. Is there a way to pick the nearest truncated value or even to round to the second decimal? Rounding up/down wont matter as long as its applied to all values the same.
I am trying to have the following result (if rounded up):
(user_id)(Map_nu)
----
1 4
2 6
3 6
4 1
5 10
6 11
7 3
Thanks!
i think you might have to do this in 2 separate queries. there is no 'nearest' operator in sql, so you can either calculate it in your software, or you could use
select map_nu from table1 ORDER BY abs(value - $avg) LIMIT 1
inside a loop. however, that cannot be used as a join function as it requires the ORDER and LIMIT which are not valid as joins.
another way of looking at it is it seems that your map_nu and value are deterministic in relation to each other - value = 1 + ((map_nu - 1) * 0.045) - so maybe you could make use of that fact and calculate an integer based on that equation? assuming that relationship holds true for all values of map_nu.
This is an awkward database design. What is the data representing and what are you trying to solve? There might be a better way.
Maybe do something like...
SELECT a.user_id, b.map_nu, abs(a.avg - b.value)
FROM
table2 a
join table1 b
left join table1 c on abs(a.avg - b.value) > abs(a.avg - c.value)
where c.value is null
order by a.user_id
Doesn't actually produce the same output as the one you were expecting for (doesn't do any rounding). Though you should be able to tweak it from there. Above query will produce the output below (w/ data you've provided):
user_id map_nu abs(a.avg - b.value)
------- ------ --------------------
1 3 0.0209999999999999
2 5 0.02
3 8 0.01833
4 1 0
5 10 0.016
6 10 0.0149999999999999
7 3 0.02
Beware though if you're dealing with large tables. Evaluate the explain of the above query if it'll be practical to run it within MySQL or if better to be done outside it.
Note 2: Will produce duplicate rows if there are avg values that are equi-distant to value values within table1 (Ex. if value for map_nu's 11 and 12 are 2 and 3 and someone get's an avg of 2.5). Your question doesn't really specify what to do for that so you might want to take that into account.
Its taking a little extra work, but I figure the easiest way to get my results will be to map all values to the second decimal place in table1:
1 1
1.01 1
1.02 1
1.03 1
1.04 1
1.05 2
1.06 2
1.07 2
1.08 2
1.09 3
1.1 3
1.11 3
1.12 3
1.13 3
1.14 4
...
Thanks for the suggestions! Sorry I couldn't present the question more clear.