MySQL Average of two selects? - mysql

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;

Related

How to make a query that brings the results of the day

I have this query but I want to bring the results processed on the day and if there is no data in excess on the day bring the last 100 processed.
SELECT * FROM tbl_classe where classe>= '2019-10-15';
You can use order by and limit (in both Postgres and MySQL):
SELECT *
FROM tbl_classe
ORDER BY classe DESC
LIMIT 100;
I'm not sure what 2019-10-15 has to do with the query. You seem to want the 100 most recent entries.
IF (SELECT COUNT(*) FROM tbl_classe WHERE classe>= '2019-10-15' ) = 0
THEN
SELECT TOP 100 * FROM tbl_classe ORDER by classe DESC, id DESC
ELSE
SELECT * FROM tbl_classe where classe>= '2019-10-15';
END
As per David's request (code seems pretty self-documenting to me..)
Count the number of records for the chosen date.
If the count is zero then get the 100 most recent records.
If the count is > zero then return the records for the day

Count the number of items per hour, then find the average of the result

I'm trying to build a query to find average number of music tracks played per broadcast hour for a given day.
I have a table that logs when a track was played, based on a datetime value (created field).
So I need to count how many entries, or tracks, where logged per hour.
Then with the hourly totals, find the average.
So far I have this, but wondered if it is correct?
SELECT AVG(a.total) FROM (
SELECT HOUR(created) AS hour, COUNT(id) AS total
FROM `music_log` r
WHERE DATE(created) = DATE( DATE_SUB(NOW() , INTERVAL 1 DAY) ) group by HOUR(r.created)
) a
I got to admit, I formulated that from another post on stackoverflow, and don't understand what the a and r mean/reference.
I would like to know if I have this right, so I can expand query to cover a quarter (3 months) results.
You can calculate the average without a subquery:
SELECT COUNT(*) / COUNT(DISTINCT DATE(created), HOUR(created) ) as average
FROM `music_log`
WHERE QUARTER(created) = 1 AND YEAR(created) = YEAR(NOW()) ;
This calculates the total count and the number of hours without the need for a subquery.
As Strawberry says, it looks like I'm on the right track. Thanks Strawberry.
To expand this, and just in case it helps anyone else, I've included the query to cover a quarter, in this case the first quarter of the current year....he says hoping there's nothing else wrong with my query :)
SELECT AVG(a.total) FROM (
SELECT DATE(created) as day, HOUR(created) AS hour, COUNT(id) AS total
FROM `music_log`
WHERE QUARTER(created) = 1
AND YEAR(created) = YEAR(NOW())
group by DATE(created), HOUR(created)
) a
In order to calculate it correctly, I needed to group the hourly results by Date and Hour.
In the previous query in the question, it was only grouping by Hour. Which is fine if the Average calculation is over just a single day, but when you expand that beyond a day, the results become incorrect. This is because it will add the total of both occurrence of 11pm, for example, then work out the average.
Hope that helps...or if I've made a mistake, I hope someone picks up on it ;)

DISTINCT ON query w/ ORDER BY max value of a column

I've been tasked with converting a Rails app from MySQL to Postgres asap and ran into a small issue.
The active record query:
current_user.profile_visits.limit(6).order("created_at DESC").where("created_at > ? AND visitor_id <> ?", 2.months.ago, current_user.id).distinct
Produces the SQL:
SELECT visitor_id, MAX(created_at) as created_at, distinct on (visitor_id) *
FROM "profile_visits"
WHERE "profile_visits"."social_user_id" = 21
AND (created_at > '2015-02-01 17:17:01.826897' AND visitor_id <> 21)
ORDER BY created_at DESC, id DESC
LIMIT 6
I'm pretty confident when working with MySQL but I'm honestly new to Postgres. I think this query is failing for multiple reasons.
I believe the distinct on needs to be first.
I don't know how to order by the results of max function
Can I even use the max function like this?
The high level goal of this query is to return the 6 most recent profile views of a user. Any pointers on how to fix this ActiveRecord query (or it's resulting SQL) would be greatly appreciated.
The high level goal of this query is to return the 6 most recent
profile views of a user.
That would be simple. You don't need max() nor DISTINCT for this:
SELECT *
FROM profile_visits
WHERE social_user_id = 21
AND created_at > (now() - interval '2 months')
AND visitor_id <> 21 -- ??
ORDER BY created_at DESC NULLS LAST, id DESC NULLS LAST
LIMIT 6;
I suspect your question is incomplete. If you want:
the 6 latest visitors with their latest visit to the page
then you need a subquery. You cannot get this sort order in one query level, neither with DISTINCT ON, nor with window functions:
SELECT *
FROM (
SELECT DISTINCT ON (visitor_id) *
FROM profile_visits
WHERE social_user_id = 21
AND created_at > (now() - interval '2 months')
AND visitor_id <> 21 -- ??
ORDER BY visitor_id, created_at DESC NULLS LAST, id DESC NULLS LAST
) sub
ORDER BY created_at DESC NULLS LAST, id DESC NULLS LAST
LIMIT 6;
The subquery sub gets the latest visit per user (but not older than two months and not for a certain visitor21. ORDER BY must have the same leading columns as DISTINCT ON.
You need the outer query to get the 6 latest visitors then.
Consider the sequence of events:
Best way to get result count before LIMIT was applied
Why NULLS LAST? To be sure, you did not provide the table definition.
PostgreSQL sort by datetime asc, null first?

Top-10 mysql query

I'm in need of a better way of retrieving top 10 distinct UID from some tables I have.
The setup:
Table user_view_tracker
Contains pairs of {user id (uid), timestamp (ts)}
Is growing every day (today it's 41k entries)
My goal:
To produce a top 10 of most viewed user id's in the table user_view_tracker
My current code is working, but killing the database slowly:
select
distinct uvt.uid as UID,
(select count(*) from user_view_tracker temp where temp.uid=uvt.uid and temp.ts>date_sub(now(),interval 1 month)) as CLICK
from user_view_tracker uvt
order by CLICK
limit 10
It's quite obvious that a different data structure would help. But I can't do that as of now.
First of all, delete that subquery, this should be enough ;)
select
uvt.uid as UID
,count(*) as CLICK
from
user_view_tracker uvt
where
uvt.ts > date_sub(now(),interval 1 month)
group by
uvt.uid
order by CLICK DESC
limit 10
Try:
select uid, count(*) as num_stamps
from user_view_tracker
where ts > date_sub(now(), interval 1 month)
group by uid
order by 2 desc limit 10
I kept your criteria as far as getting the count for just the past month. You can remove that line if you want to count all.
The removal of DISTINCT should improve performance. It is not necessary if you aggregate in your outer query and group by uid, as that will aggregate the data to one row per uid with the count.
You should use Aggregate functions in MySQL
SELECT UID, COUNT(ts) as Number_Of_Views FROM user_view_tracker
GROUP BY UID
ORDER BY Number_Of_Views DESC
LIMIT 10
A simple demo which selects the top 10 UID viewed
http://sqlfiddle.com/#!2/907c10/3

MySQL query predominant non-numeric value

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