MySQL query predominant non-numeric value - mysql

I'm looking for a function to return the most predominant non numeric value from a table.
My database table records readings from a weatherstation. Many of these are numeric, but wind direction is recorded as one of 16 text values - N,NNE,NE,ENE,E... etc in a varchar field. Records are added every 15 minutes so 95 rows represent a day's weather.
I'm trying to compute the predominant wind direction for the day. Manually you would add together the number of Ns, NNEs, NEs etc and see which there are most of.
Has MySQL got a neat way of doing this?
Thanks

It's difficult to answer your question without seeing your schema, but this should help you.
Assuming the wind directions are stored in the same column as the numeric values you want to ignore, you can use REGEXP to ignore the numeric values, like this:
select generic_string, count(*)
from your_table
where day = '2014-01-01'
and generic_string not regexp '^[0-9]*$'
group by generic_string
order by count(*) desc
limit 1
If wind direction is the only thing stored in the column then it's a little simpler:
select wind_direction, count(*)
from your_table
where day = '2014-01-01'
group by wind_direction
order by count(*) desc
limit 1
You can do this for multiple days using sub-queries. For example (assuming you don't have any data in the future) this query will give you the most common wind direction for each day in the current month:
select this_month.day,
(
select winddir
from weatherdatanum
where thedate >= this_month.day
and thedate < this_month.day + interval 1 day
group by winddir
order by count(*) desc
limit 1
) as daily_leader
from
(
select distinct date(thedate) as day
from weatherdatanum
where thedate >= concat(left(current_date(),7),'-01') - interval 1 month
) this_month

The following query should return you a list of wind directions along with counts sorted by most occurrences:
SELECT wind_dir, COUNT(wind_dir) AS count FROM `mytable` GROUP BY wind_dir ORDER DESC
Hope that helps

Related

Count sum of different rows and save in a single row BigQuery

I am doing the data cleaning in a BigQuery. I managed to count each of the variables. However there are some redundant info with different variables, so I need to merge the number and save the overall total in a single row.
This is my work:
SELECT
day,
COUNT(*) as Total,
FROM
table
where day<> 'null'
GROUP BY day
-- HAVING COUNT(*) >= 10?
ORDER BY COUNT(*) DESC;
The result is
What should I add so the Monday and Mndy is added in a single row? Thanks
SELECT
CASE WHEN day in ('Monday', 'Mndy') THEN 'Monday' ELSE day END day,
COUNT(*) as Total,
FROM
table
where day<> 'null'
GROUP BY 1
-- HAVING COUNT(*) >= 10?
ORDER BY COUNT(*) DESC;

I need the way to aggregate based on column value using MySQL

I am learning Charts in Laravel, i need to draw Line graph for daily Student Attendance for those students come late or on time. I tried to write MYSQL query but it doesn't work
I tried subquery on same table to get data for daily students and i also need 7 dates only not full date, like date is stored in db as 09/08/2019 but i need it as 08 as date.
SELECT Date, COUNT(*) AS TimeStudent
FROM attendance WHERE `Attendance`='OnTime' AND (SELECT COUNT(*) AS
LateStudent FROM attendance
WHERE `Attendance`='Late'
GROUP BY `Date`
ORDER BY LateStudent DESC)
GROUP BY `Date`
ORDER BY TimeStudent DESC
but i got
[Err] 1241 - Operand should contain 1 column(s)
, because i can't use to fetch Date again in subquery while use it after where clause. Any one help me plz.
Here is a way to aggregate based on column value.
This query will give you count of on time and late student for a particular date.
SELECT
`Date`,
DATE_FORMAT(`Date`, '%d') AS Month_Date, -- You can modify it as per your requirement
SUM(IF(`Attendance` = 'OnTime', 1, 0)) AS OnTime_Count,
SUM(IF(`Attendance` = 'Late', 1, 0)) AS Late_Count
FROM attendance
WHERE `Date` >= CURRENT_DATE - INTERVAL 7 DAY
GROUP BY `Date`;

Select all distinct values where datestamp is in the last 24 hours and order by total rows ASC

I have a query I am trying to formulate, but it keeps giving me unexpected results.
What I need to do is:
select all distinct values from my table where the unix timestamp is >= the last 24 hours, then order these results by which one has the highest amount of entries.
I have managed the time part:
SELECT DISTINCT(column_name) as myValue from table_name WHERE time_column >= unix_timestamp(CURRENT_TIMESTAMP, INTERVAL 1 DAY)
This works as expected. Then I was just going to use PHP to sort through the results etc etc, however I wish to use the power of SQL on this one.
Any ideas how I can extend the above query to encapsulate counting the amount of distinct column_name values? Also to then sort this in order dependent on how many values are in each one?
So essentially I want to get my results like so :
a unique ID | highest amount
a unique ID | second highest amount
a unique ID | lowest amount
I think you want to use group by for this query:
SELECT column_name as myValue, count(*) as cnt
from table_name
WHERE time_column >= unix_timestamp(CURRENT_TIMESTAMP, INTERVAL 1 DAY)
GROUP BY column_name
ORDER BY cnt;
I managed to figure it out, and in my case it works perfectly:
SELECT column_name, COUNT(*) as myValue
FROM table_name
WHERE time_column >= unix_timestamp(CURRENT_TIMESTAMP - INTERVAL 1 DAY)
GROUP BY column_name
ORDER BY myValue DESC
This gave me the 3 values which I expected. Which were the 3 values in the last 24 hours, and they were ordered by the amount of occurrences of this were in the database table - I tested this by manually creating another occurrence of these and checking at each stage. Worked a treat

MySQL Average of two selects?

I'm trying to take the average time of two selects and return them
to see what percentage of time has gone by since the last order. It
is part of an early alert system if you're wondering why.
Select 1 takes 5 of the (almost) most current datetimes, records 2-6
for example to get the average of some of the last ordered products.
Select 2 (I don't think its working) takes the average of the current
order and NOW() to see how much time has gone by since the last order.
The return should be the average time between those recent orders and
the last order placed. I evidently have some bugs in my code, and can
not get it to work...
I dunno, I'm hoping some obvious stuff sticks out, like how I botched the
UNION() or muddled the second TIMESTAMPDIFF()
SELECT (spread + recent) / 2 AS lapse FROM
(SELECT TIMESTAMPDIFF(MINUTE, MIN(created_at), MAX(created_at) )
/
(COUNT(DISTINCT(created_at)) -1)
FROM ( SELECT created_at
FROM dbname.sales_flat_order_status_history
ORDER BY created_at DESC LIMIT 5 OFFSET 1
)
AS created_at) AS spread,
UNION
(SELECT TIMESTAMPDIFF(MINUTE, MIN(created_at), NOW() )
/
(COUNT(DISTINCT(created_at)) -1)
FROM ( SELECT created_at
FROM dbname.sales_flat_order_status_history
ORDER BY created_at DESC LIMIT 1
)
AS created_at) AS recent;
ORDER BY lapse LIMIT 1;

mysql query: how to get the number of yes/no votes per day

I have to create a mysql query to get a voting distribution of each day exceeding a particular date, something like this...
date yes_votes no_votes
------------------------------------------
2010-01-07 21 22
2010-01-07 2 0
My table is like this..
post_votes
--------------------------
id(longint)
date(timestamp)
flag(tinyint) // this stores the yes/no votes 1-yes, 2-no
I am stuck at this....
SELECT COUNT(*) AS count, DATE(date) FROM post_votes WHERE date > '2010-07-01' GROUP BY DATE(date)
this gives the total number of votes per day, but not the distribution that I want.
SELECT COUNT(*) AS count
, DATE(date)
, SUM(flag = 1) AS yes_votes
, SUM(flag = 2) AS no_votes
FROM post_votes
WHERE date > '2010-07-01'
GROUP BY DATE(date)
This is a trick that works in MySQL, as flag=1 will either be True or False. But True = 1 and False = 0 in MySQL so you can add the 1s and 0s using the SUM() function.
Other solutions with IF or CASE would be better for clarity or if there is any chance you want to move the database to another RDBMS.
Comments not related to the question:
It's bad habit to use reserved words like date or count for naming fields or tables.
It's also not good to use "date" when you actually store a timestamp. Names should reflect use.
For table names it's recommended to use singular (post_vote) and not plural - although many use plural, it gets confusing in the end. Plural is good for some fields or calulated fields, like your yes_votes and no_votes where we have a counting.
Sum it:
select date(date) as date,
sum(case when flag = 1 then 1 else 0) as yes,
sum(case when flag = 2 then 1 else 0) as no
from post_votes
where date > '2010-07-01'
group by date(date)
you are almost at the solution :)
i would recommend the use of an IF condition in a SUM method like so:
SELECT SUM(IF(flag = 'yes',1,0)) AS yes_count,
SUM(IF(flag = 'no',1,0)) AS no_count,
DATE(date)
FROM post_votes
WHERE date > '2010-07-01'
GROUP BY DATE(date)
this will allow for the function to add 1 to each sum only if the value is equal to yes/no
SELECT DATE(date) as dt,
sum(if(flag=1,1,0)) as yes,
sum(if(flag=2,1,0)) as no
FROM post_votes WHERE date > '2010-07-01'
GROUP BY dt
I had that problem too. The best solution of that I can think of, is to split the "flag" in two fields, like:
upvote(tinyint)
downvote(tinyint)
Then you are able to count them very easy and without mysql-voodoo:
SELECT
SUM(upvote) AS up,
SUM(downvote) AS down,
DATE(`date`) AS Created_at
FROM post_votes
WHERE Created_at > '2010-07-01'
GROUP BY Created_at
Btw.: You should not name a column date, because it's a MySQL-Keyword.