SQL: Select last 15 records from mysql grouped rows - php

Here is my query:
SELECT temp_table.*
FROM
( SELECT COUNT(*) as hits_count
, date
FROM visits
GROUP
BY date
) as temp_table
ORDER
BY temp_table.date ASC
LIMIT 15
I insert a new record into this table each time an user access a page. I need to get those records stacked by their date. It worked untill it hit the limit of 15 days, so now it doesn't show other days, it stops on his limit(15).
To make it clearer, let say I have stored 20 days, it shows just the 1-15 day interval, but i need it to get from db the interval 5-20, and so on.

I think this is what you are looking for:
SELECT temp_table.* FROM (
SELECT COUNT(*) as hits_count, date FROM visits GROUP BY date
) as temp_table ORDER BY temp_table.date DESC LIMIT 15
Not sure about the limit part though.

Related

Is it possible to select 10 rows for each group by date(timestamp) in mysql table ? How to proceed?

I have a table with attributes as timestamp, SensorName, Temperature, Humidity. What I doing is getting results by ordering then according to the timestamp in DESC order and I have condition to get it for either 1 day 7 days or for a previous month. But the issue is I am getting a Lot more values when I access old records. What I need to do is, since my data is ordered by timestamp, I need at most 15 to 20 rows/records for each date.Suppose I am getting data from June 10 to June 17, and each date have 100 records. I need only 10/20 records for the particular day (top 20 for each day).
My MySQL version is 5.7.26 and i tried using ROW_NUMBER but it is not helping
SELECT datestamp AS TIME,Temperature AS TEMPERATURE FROM table_name WHERE NodeAdd = 'SensorName' and datestamp >= DATE_ADD(CURRENT_DATE,INTERVAL -'$somevar' DAY) ORDER BY datestamp DESC
The above code shows how I am getting data for different days, The $somevar variable is hardcoded, If user select day it is -1 if he selects previous week, it is -7 and -30 for the previous month.. I need at most 20 rows/records for each day.
NOTE :: I don't have an ID column or a Unique/Primary Key in my Table, so I was trying to get particular rows using partitioning via dates only.
You need to create Row Number per group which is Date and then only keep records with row Row Number < 10 as you wants 10 records per group. The following script is just a guideline and you can fit it with your table structure to get your desired output-
SELECT * FROM
(
SELECT *,
(
CASE DateColumn
WHEN #DateColumn THEN #curRow := #curRow + 1
ELSE #curRow := 1 AND #DateColumn := DateColumn
END
) AS rank
FROM
(
SELECT *,CAST(<your_date_column> AS DATE) AS `DateColumn`
FROM Your_table
)A
,(SELECT #curRow := 0, #DateColumn := '') r
ORDER BY <your_date_column>
)A WHERE Rank < 11

Show all dates even those with zero data in it in mySQL?

My following query shows the date and the count of the emails found on each day (last 2 days)
My problem is that if no emails are found today, the today date will not be displayed on the output. (if yesterday has emails, it will show only 1 row with yesterday date and email).
How can I edit my query to always show 2 rows, today and yesterday, date and number of emails even zero?
SELECT maildate,
COUNT(*) AS totalEmails
FROM emails
WHERE maildate >= Date_add(Curdate(), interval - 2 DAY)
AND company_id = 1
GROUP BY DATE(maildate)
ORDER BY maildate desc
There are many tricks to creating a list of dates (or numeric sequences similarly). The one I like to use with MySQL is using #sqlvariables. I will typically start with a baseline value such as your date -2 days. I will do a cross-join to any other table in the database that has at least as many records as you expect in your output... Say 30 days, or a whole year 366 days, or longer. The inner sql variable prep will keep increasing itself by whatever increment (you could even do date ranges such as begin/end of a week, month, etc). Now you have your table of all possible dates you are looking to fill.
Now, I do a secondary query by the value -- in this case your email date and apply the group by. Using the where clause in this query will make IT faster since it can utilize the date on its query result set before returning for the LEFT-JOIN to the date range result set.
Now, your simple left-join gets both parts of all dates to be included and those corresponding counts that do exist.
Note the table alias "AnyTableWithAtLeast3RecordInIt" in the "JustDates" query could in-fact be your "emails" table. Since we don't care about any criteria except a record exists, and we are applying a limit of 30 days in my example, it will be instantaneous.
select
JustDates.DateToInclude,
coalesce( SumCnts.TotalEmails, 0 ) TotalEmails
from
( select
#myDate := DATE_ADD( #myDate, INTERVAL 1 DAY ) as DateToInclude
from
( select #myDate := Date_add(Curdate(), interval - 2 DAY) ) as SQLVars,
AnyTableWithAtLeast3RecordInIt
limit 30 ) JustDates
left join
( select
maildate,
COUNT(*) AS totalEmails
FROM
emails
WHERE
maildate >= Date_add(Curdate(), interval - 2 DAY)
AND company_id = 1
GROUP BY
DATE(maildate) ) SumCnts
ON JustDates.DateToInclude = SumCnts.MailDate
Now, judging by your query, but unclarified request... Your emails table CAN HAVE FUTURE DATES? Is that correct? Such as a Dr. Office and appointments are for the future and you want to get emails out for a given range. This is what I was inferring and hence had my limit to only go out 30 days... If you need longer, just extend the LIMIT clause.
You need a table that contains all dates in the needed range. If its only about today and yesterday, you can easily create it as a subquery (derived table).
SELECT Curdate() as maildate
UNION ALL
SELECT Curdate() - INTERVAL 1 DAY
http://rextester.com/ALH50651
Now you can LEFT JOIN your table and count the rows:
SELECT sub.maildate,
COUNT(m.maildate) AS totalEmails
FROM (
SELECT Curdate() as maildate
UNION ALL
SELECT Curdate() - INTERVAL 1 DAY
) sub
LEFT JOIN emails m
ON DATE(m.maildate) = sub.maildate
AND m.company_id = 1
GROUP BY sub.maildate
ORDER BY sub.maildate desc

Daily usage time in Mysql database

I am trying to achieve the Sum of Hours spent per day, where my mysql database has multiple logging records of every activity they perform (e.g; login, view, update, logout). What i am trying to do is SELECT (all records of a particular day) and find the difference in epoch time between the first and last entry giving me the 'Time Spent' for that period. Later add it by Month etc.
Database schema;
id, userid, time, action
**I can select the first and last entry from the query below:
**
SELECT
(SELECT time FROM log WHERE time(myDate) = DATE(NOW()) ORDER BY time LIMIT 1) as 'first',
(SELECT column FROM table WHERE time(myDate) = DATE(NOW()) ORDER BY time DESC LIMIT 1) as 'last'
But i am guessing a cross join or SUM for all these have to happen. Some guidance would be much appreciated.

Php mysql get the nearest-latest record if a record is not exist (datetime based)

Trying to get my head around, If I select a record such as WHERE item_id='$item_id' AND date(datetime)='2012-06-25' and if that record does not exist so I want to get the nearest-latest record after that date. How can I achieve that in a query?
All I can think of the only way right now is if num_of_rows is 0 then I add 3 days period ahead to that day and search again and get the DESC datetime LIMIT 1 (in case there are multiple rows). But who knows I can do it with just a query.
The record could have multiple rows in one day. So if a particular date has no record, how to get the next nearest available data given the same $item_id?
SELECT *
FROM table
WHERE field <= '2012-06-25'
ORDER BY field DESC
LIMIT 1
I think this is what you are looking for:
SELECT *
FROM my_table
WHERE datetime BETWEEN '2012-06-25 00:00:00' AND
DATE_ADD('2012-06-25 00:00:00', INTERVAL 3 DAY)
ORDER BY datetime ASC
LIMIT 1;
also create index on field datetime for faster performance.
This will bring back the item closest to the date that you enter into the query. It won't however look for before or after, just find the closest date to what you enter in.
select
min(abs(DATEDIFF(date(datetime),'2012-06-25'))) as minDiff
,yourID
from table1
group by yourID
order by 1 asc;

Complex SQL query... 3 tables and need the most popular in the last 24 hours using timestamps

I have 3 tables with a column in each which relates to one ID per row. I am looking for an sql statement query which will check all 3 tables for any rows in the last 24 hours (86400 seconds) i have stored timestamps in each tables under column time.
After I get this query I will be able to do the next step which is to then check to see how many of the ID's a reoccurring so I can then sort by most popular in the array and limit it to the top 5...
Any ideas welcome! :)
Thanks in advance.
Stefan
SELECT id, COUNT(*) AS cnt
FROM (
SELECT id
FROM table1
WHERE time >= NOW() - INTERVAL 1 DAY
UNION ALL
SELECT id
FROM table2
WHERE time >= NOW() - INTERVAL 1 DAY
UNION ALL
SELECT id
FROM table3
WHERE time >= NOW() - INTERVAL 1 DAY
) q
GROUP BY
id
ORDER BY
cnt DESC
LIMIT 5

Categories