Using MySQL to select data from the last three months - mysql

I have a table which contains the following columns:
ID = unique identifier in ascending order
ProductId = Id of a product
rate1 to rate5 = number of times that product has recived a 1 star, 2
star, 3 star, 4 star or 5 star rating
aveRate = average rating for that product
lastSubDate = last time a review was submitted for that product
And I'm trying to write an SQL statement which selects the ProductId's which have the highest number of 5 star ratings also with an average rating of 5 and the last review submission was within the last three months.
The table looks like this example:
ID ProductId rate1 rate2 rate3 rate4 rate5 aveRate lastSubDate
18 9996637 0 0 0 0 1 5 2011-08-10 12:00:34
26 9996628 1 0 0 0 0 1 2010-05-06 05:45:05
34 9996618 0 0 0 1 0 4 2011-10-09 09:00:45
36 9996614 5 0 0 0 0 1 2011-01-05 09:30:32
48 9996592 5 0 1 0 3 3 2012-11-28 19:00:06
66 9996566 0 0 0 1 3 5 2011-04-06 06:45:34
70 9996562 0 0 0 1 1 5 2011-05-17 18:30:03
This is the query I've got so far:
SELECT `ProductId`,`rate5`,`aveRate`,`lastSubDate`
FROM ratings
WHERE `aveRate` = 5 AND `lastSubDate` > '24 Feb 2013'
ORDER BY `rate5` DESC
LIMIT 3
This returns the products with the most 5 star reviews which also have an average rating of 5, however it doesn't limit the results to the last three months as I want. How can I amend this statement to also select data from only the last three months?

Your date constant is in the wrong format. Try this if you're using a constant date:
... AND `lastSubDate` > '20130224'
You can also use 20130224 (without the quotes) or '2013-02-24' above - see the MySQL Date and Time Literals documentation.
Or to calculate "three months ago" just do this:
... AND `lastSubDate` > CURDATE() - INTERVAL 3 MONTH
Finally, you don't need the backticks here. If you find them distracting you can drop them:
... AND lastSubDate > whatever

Related

Getting messages within 5 minutes from a specific ID and timestamp MYSQL

I'm building a chat app retrieving chat history when a certain chat is expanded but i want a function or functions that can help me get chats that are 5 minutes within each other and are sent by the same user let's say given this table below
id
message
msg_owner_id
msg_reciever
msg_time
msg_type
seen
seen_time
note(not part of table)
1
hey
20
6
10:42:51
interchats
0
<----- 20 sent to 6
2
hi
20
6
10:43:20
interchats
0
<------20 sent to 20
3
am fine
20
6
10:44:11
interchats
0
<------20 sends to 6 again
4
mannnn
6
20
10:45:02
interchats
0
<-- 6 replies to 20
5
mannnn
20
11
10:53:02
interchats
0
<-- 20 sends to 11
I have used the following code however some values are missing
SELECT GROUP_CONCAT(id), DATE_FORMAT(msg_time, '%Y-%m-%d %H:%i'),
id as ID, msg_owner_id as MSG_OWNER, msg_reciever as MSG_RECEIVER,
message as MESSAGE
FROM chats WHERE msg_time >= :msg_time - INTERVAL 5 MINUTE AND id >= :id
GROUP BY 2 ORDER BY 2
let's say we need to start from id 1 and timestamp 10:42:51, how do I select all the chats sent within a 5 minutes interval from ID 1 and timestamp 10:42:52
Desired result should be:
the following IDs returned 1, 2 and 3

MySQL locate first and last event per day

I have a string of events being logged on a 5 minute basis throughout the day in a MySQL DB. I need to identify the first event (where logid > 0) of the day as well as the last (where logid=0), but struggling to find a simple SQL solution.
A 0 will be stored in the logid field in every row starting at midnight until the first event is triggered, at which point it will change to a number > 0. Then various events will be triggered logging a number > 0 for the remainder of the day, at which point the field will once again be logged as 0 until midnight, when the process starts over again.
Is there a quick and simple way to pull the rows identifying the time when the events start, and another result showing when the events end?
CREATE TABLE logs(
id INT AUTO_INCREMENT,
date DATETIME,
logid INT,
PRIMARY KEY (id)
) ENGINE=INNODB;
This is the test data:
id date logid
1 2018-11-12 01:05:00 0
2 2018-11-12 01:10:00 0
3 2018-11-12 01:15:00 0
4 2018-11-12 01:20:00 0
5 2018-11-12 01:05:00 0
…
84 2018-11-12 06:35:00 0
85 2018-11-12 06:35:00 1
86 2018-11-12 06:40:00 1
87 2018-11-12 06:45:00 1
88 2018-11-12 06:50:00 1
…
164 2018-11-12 15:20:00 1
165 2018-11-12 15:25:00 0
166 2018-11-12 15:30:00 0
167 2018-11-12 15:35:00 0
Desired Result set:
85 2018-11-12 06:35:00 1
165 2018-11-12 15:25:00 0
I'm not concerned about logid up until the first instance where it is greater than 0. But I need to identify the first instance where logid > 0, and then the next chronological instance where logid = 0 again.
My primary attempt was to group and order on the date and logid (edit: failed attempt removed for clarity)
Here's my latest attempt
(SELECT *
FROM logs
WHERE logid>0
GROUP BY date
ORDER BY date
limit 1
)UNION ALL(
SELECT *
FROM logs
WHERE logid>0
GROUP BY date
ORDER BY date DESC
limit 1)
Getting closer, but not quite there. This gives me the correct first row where logid = 1, but it gives me the last row where logid = 1 (id 164) rather than the following row where logid = 0 (id=165).
Is it possible to select the penultimate row of a set if I change limit 1 to 2?
Any other pointers to keep me moving forward?
This question doesn't seem to be a problem for others, but I thought I would post the answer I came up with in case anyone runs into a similar situation in the future.
SET #v1 := (SELECT date
FROM logs
WHERE logid > 0
GROUP BY date
ORDER BY date
limit 1);
(SELECT *
FROM logs
WHERE date>#v1 and logid>0
GROUP BY date
ORDER BY date
limit 1
) UNION ALL (
SELECT *
FROM logs
WHERE date>#v1 and logid=0
GROUP BY date
ORDER BY date
limit 1
)

count ocurrences over each day in mysql

I'm having some problems figuring out how to solve but I can't come with an answer at all.This is my problem.
I have a mySQL table like the following:
cust_id,date_removed,station_removed,date_arrived,station_arrived
6,"2010-02-02 13:57:00",56,"2010-02-02 13:58:00",77
6,"2010-02-02 15:12:00",66,"2010-02-02 15:12:00",56
30,"2010-02-05 11:36:00",32,"2010-02-05 11:37:00",14
30,"2010-02-05 11:37:00",14,"2010-02-05 11:37:00",20
30,"2010-02-05 12:41:00",85,"2010-02-05 12:43:00",85
30,"2010-02-05 12:44:00",85,"2010-02-05 12:46:00",85
30,"2010-02-06 13:15:00",8,"2010-02-06 13:17:00",20
30,"2010-02-06 13:18:00",23,"2010-02-06 13:19:00",23
30,"2010-02-06 13:20:00",32,"2010-02-06 13:21:00",39
30,"2010-02-06 13:21:00",11,"2010-02-06 13:21:00",23
30,"2010-02-06 13:21:00",76,"2010-02-06 13:22:00",32
which the corresponding datatypes in each field is the following:
cust_id: varchar()
date_removed: datetime
station_removed: int
date_arrived: datetime
station_arrived: int
Next, I was asked to make a query to get the count over every station used along the day, to get a table like this one:
station 2010-02-02 2010-02-05 2010-02-06
56 2 0 0
66 1 0 0
32 0 1 2
14 0 2 0
85 0 2 0
8 0 0 1
23 0 0 2
11 0 0 1
76 0 0 1
77 1 0 0
20 0 1 1
39 0 0 1
where the columns are the days and the rows are each station. I'm not a very good mySQL user neither.
Could somebody help me on this one?.
Thank you in advance
Use this query :
select stations.name as station,
(select count(*) from table where date(date_arrived)='2010-02-02' and (station_removed=stations.name or station_arrived=stations.name)) as '2010-02-02'
(select count(*) from table where date(date_arrived)='2010-02-05' and (station_removed=stations.name or station_arrived=stations.name)) as '2010-02-05'
(select count(*) from table where date(date_arrived)='2010-02-06' and (station_removed=stations.name or station_arrived=stations.name)) as '2010-02-06'
from
(select station_removed as name from table
union
select station_arrived from table ) stations ;

Query that returns quantity of repeated values

In mysql, I need a query that returns the quantity of repeated values in the field "Info" of my table "Log".
Table Log:
ID_Log User Info
1 1 3
2 1 3
3 1 3
4 1 5
5 1 6
6 1 6
7 1 7
8 1 8
9 1 8
The query should return "4" (Info 3 appears three times, Info 6 appears two times, Info 8 appears two times).
Any suggestions?
You can get the number of values that have already appeared by using a simple subtraction. Subtract the number of distinct values from the total number of rows:
select count(*) - count(distinct info)
from log;
The difference is the number that "repeat".
This should work. Group the values of info together and only keep the results where the number of occurrences minus 1 is greater than 0. Then sum the numbers of occurrences.
select sum(repeats)
from (SELECT Info, count(*) - 1 AS repeats
FROM Log
GROUP BY Info
HAVING repeats > 0)

mySQL to retrieve records that repeat a value in order

I have a big table with 300,000 records. This table has a integer value called "velocity" and it`s value is from 0 to 100.
In the firsts records, the value is 0 and I want to remove. I want to remove from the query, the records where the velocity field repeats more than 10 times. For example:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 5 10 12 13 15 20 30 20 15 10 8 5 2 1 0 0 0 0 4 5 10 20...
[-------remove this-----------].......................................................................[---------] <- do not remove this
Thanks
The easiest way to do this is with a loop.
You can write a stored procedure that iterates through the records, or you might do it outside of the database. I'd do it like that if this needs to be done once. If this is a continuous process, it's better to make sure that the extra data is just not inserted into the database in the first place.
Anyway, if you insist on doing this in pure SQL, without stored procedures with loops, you can use a query like this:
set #groupnum=0;
select
GroupNum,
count(*) as RecsInGroup
from
(
select
t1.id as Id,
t1.velocity as velocity1,
t2.velocity as velocity2,
if(t1.velocity<>t2.velocity,#groupnum:=#groupnum+1,#groupnum) as GroupNum
from
VelocityTable as t1
join
VelocityTable as t2
on
t1.id=t2.id-1
) as groups
group by
GroupNum
having RecsInGroup>10
What happens here?
Step 1
The inner query just selects all records in your table, but splits the data in sequential groups.
So, using your example, it does this:
velocity : 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 5 10 12 13 15 20 30 20 15 10 8 5 2 1 0 0 0 0 4 5 10 20
Groupnum : 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 18 18 18 19 20 21 22
It does that by joining the table to itself, by linking subsequent records in the table. Every time the left and right velocity are different, the GroupNum is increased. Otherwise it's left unchanged.
Step 2
The result if the query is wrapped in an outer query, and grouped by GroupNum. Again, using your example it would result in this:
GroupNum,RecsInGroup
0,15 // !!
1,1
2,1
3,1
4,1
5,1
6,1
7,1
8,1
9,1
10,1
11,1
12,1
13,1
14,1
15,1
16,1
17,1
18,4 // !!
19,1
20,1
21,1
By Adding the having RecsInGroup>10 clause, the result becomes this:
GroupNum,RecsInGroup
0,15
Now, with this list of GroupNum's you can delete records.
Step 3
With the query above you have:
A list of all your records, with an added GroupNum column.
The list of GroupNum's that need to be removed.
Deleting the records should be easy at this point.
I'd just rip through the records sequentially, with a variable sized window that expands and contracts to comprehend identical values. Whenever the size is >= 10 when the value changes, delete the rows using the primary keys.
You can put BEGIN TRAN and COMMIT TRAN at the beginning and end of the DELETE statements to make things reasonably efficient.
thank you very much. I'm allmost there, but i tried it with a mySQL View as table source and it's not working (unkown table xxx). I can't use the whole table because it's have more than 19 millions records, I just need the record from a specific day, vehicle plate and city.