Mysql: Execute query for each date - mysql

I am using Mysql 5.5.43-0+deb7u1.
I have managed to create this query to fetch rain data for particular day (I use MODbecause rain data is updated at every full hour while other data gets update more frequently.)
SELECT date,SUM(rainmm) FROM weather WHERE MOD(minute(time),60)=0 AND date=CURDATE()-1;
+------------+-------------+
| date | sum(rainmm) |
+------------+-------------+
| 2015-06-23 | 0.1 |
+------------+-------------+
1 row in set (0.15 sec)
I am looking for a way to get results for all days with single query instead of needing to check every day manually. I am unsure if I should use loops and iterate number for days from current date or if there is better way to accomplish this.
Desired result:
SELECT date, [Smart query to get all days at once]
+------------+-------------+
| date | sum(rainmm) |
+------------+-------------+
| 2015-06-23 | 0.1 |
| 2015-06-24 | 0.0 |
| ... | ... |
| 2015-11-11 | 11.1 |
+------------+-------------+

Does this do what you want
SELECT date,SUM(rainmm) FROM weather WHERE MOD(minute(time),60)=0
GROUP BY date
ORDER BY date;

Related

Something curious is happening subtracting dates in a query - 70 days appears from nowhere :-/ [duplicate]

the leetcode question 197.Rising Temperature
Given a Weather table, write a SQL query to find all dates' Ids with higher temperature compared to its previous (yesterday's) dates.
+---------+------------------+------------------+
| Id(INT) | RecordDate(DATE) | Temperature(INT) |
+---------+------------------+------------------+
| 1 | 2015-01-01 | 10 |
| 2 | 2015-01-02 | 25 |
| 3 | 2015-01-03 | 20 |
| 4 | 2015-01-04 | 30 |
+---------+------------------+------------------+
For example, return the following Ids for the above Weather table:
+----+
| Id |
+----+
| 2 |
| 4 |
+----+
i didn't know the function DATEDIFF(),so i wrote my sql solution:
select w1.Id
from Weather w1,Weather w2
where w1.RecordDate - w2.RecordDate = 1
and w1.Temperature > w2.Temperature
and i went through the testcase but got a wrong submit,the right solution is use funtion DATEDIFF()
select w1.Id
from Weather w1,Weather w2
where DATEDIFF(w1.RecordDate,w2.RecordDate)=1
and w1.Temperature > w2.Temperature
so my question is what's the difference between
DATEDIFF(w1.RecordDate,w2.RecordDate)=1and w1.RecordDate - w2.RecordDate = 1
thank you for your help
If the datatype of RecordDate is DATETIME rather than DATE, subtracting them returns a large value that contains the difference between the times as well as the dates. E.g.
mysql> select cast('2019-03-21 10:20:30' as datetime) - cast('2019-03-11 9:15:20' as datetime) as difference;
+-----------------+
| difference |
+-----------------+
| 10010510.000000 |
+-----------------+
But if they're DATE then subtraction should be the same as DATEDIFF():
mysql> select cast('2019-03-21' as date) - cast('2019-03-11' as date) as difference;
+------------+
| difference |
+------------+
| 10 |
+------------+
When we do simple addition and subtraction on the date or datetime, it will convert it into a number and after that the actual operation will execute. After the operation execution, the output will not be the date datatype.
For example,
For addition (+) : -
'2020-07-31' + 1 => 20200732
For subtraction (-) : -
'2020-08-01' - '2020-07-31' => 70
It should return 1 but as they consider it as a number so they return 70 instead of 1.
This is the reason we cannot apply direct addition or subtraction on date.
To get the actual difference between two dates one should must use the DateDiff().
Datediff(cast('2020-08-01' as Date),Cast('2020-07-31' as Date)) => 1

Get sum() in two columns in Laravel 5.4

I have this table (Pickups):
+-----------+------------+-------------+------------+
| worker_id | box_weight | bag_weight | date |
+-----------+------------+-------------+------------+
| 1 | 2 | 5 | 11-07-2018 |
| 1 | 7 | 9 | 11-07-2018 |
| 2 | 8 | 11 | 11-07-2018 |
| 2 | 7 | 12 | 11-07-2018 |
+-----------+------------+-------------+------------+
and I want in Laravel 5.4 Eloquent database engine get the sum of the box_weight and the bag_weight like this:
+-----------+-----------------+-----------------+------------+
| worker_id | sum(box_weight) | sum(bag_weight) | date |
+-----------+-----------------+-----------------+------------+
| 1 | 9 | 14 | 11-07-2018 |
| 2 | 15 | 23 | 11-07-2018 |
+-----------+-----------------+-----------------+------------+
Until now I could only retrieve the sum of a single column not the both in the same call.
Please find the answer bellow, since you didn't mention you want sum of same date per worker id or all dates, I assume only same date, if you want sum of all dates per worker id, remove date from groupBy
Eloquent Query
Pickup::select(['worker_id ','date',DB::raw('sum(box_weight)'),DB::raw('sum(bag_weight)')])
->groupBy('worker_id','date')
->get();
or in Query Builder Approach
DB::table('pickups')
->select(['worker_id ','date',DB::raw('sum(box_weight)'),DB::raw('sum(bag_weight)')])
->groupBy('worker_id','date')
->get();
You're looking for the MySql query or Laravel's QueryBuilder/Eloquent?
I'm assuming you want it grouped by worker_id and not by date, if it's by date, just add date to the groupBy
In the future, show us what you've tried and you're trying to accomplish in more detail
If you're looking for the MySqlQuery, Rom's answer will do just fine
SELECT worker_id, sum(box_weight), sum(bag_weight), date
FROM pickups
GROUP BY worker_id
If you're going from the Eloquent model:
//Assuming Pickup is your model name
Pickup::selectRaw('worker_id, sum(box_weight), sum(bag_weight), date')
->groupBy('worker_id')->get();
Using DB
DB::table('pickups')->selectRaw('worker_id, sum(box_weight), sum(bag_weight), date')
->groupBy('worker_id')->get();
//Or even
DB::select(DB::raw('SELECT worker_id, sum(box_weight), sum(bag_weight), date
FROM pickups
GROUP BY worker_id');
This will give you a collection of pickups, place toArray() at the end of the query if you wish to convert it to an array
The reason behind selectRaw is due to not being able to use ->sum() with ->select(). It works just fine for the sum of a column, not for multiple output and the same goes for select, as it can't relate sum(column) as a column

Obtaining max values for each day in the past 28 days

I've seen some of the past posts where there were questions about extracting max values for each day. Based on this, I tried SELECT ts, MAX(current) FROM mytable WHERE ts > date_add(now(), interval -28 day); but I only got one row back which is not what I want.
In this table, ts is my timestamp and current is another column of values. I want to get the max current values for each day in the past 28 days. However, my current values are recorded into the table every 30 mins each day. Therefore, there are many ts values for each day. Could this be the reason why the above query design doesnt work? If so, how can I amend it?
Here is an example of how my table look like for a few rows:
+---------------------+--------------+
| ts | current |
+---------------------+--------------+
| 2018-01-20 16:27:10 | 439.37 |
| 2018-01-20 17:00:18 | 378.07 |
| 2018-01-20 17:30:15 | 204.80 |
| 2018-01-20 18:00:16 | 196.50 |
| 2018-01-20 18:30:16 | 179.40 |
| 2018-01-20 19:00:16 | 183.00 |
| 2018-01-20 19:30:16 | 105.00 |

MySQL query with list of values

I have a table with over then 50kk rows.
trackpoint:
+----+------------+-------------------+
| id | created_at | tag |
+----+------------+-------------------+
| 1 | 1484407910 | visitorDevice643 |
| 2 | 1484407913 | visitorDevice643 |
| 3 | 1484407916 | visitorDevice643 |
| 4 | 1484393575 | anonymousDevice16 |
| 5 | 1484393578 | anonymousDevice16 |
+----+------------+-------------------+
where 'created_at' is a timestamp of row added.
and i have a list of timestamps, for example like this one:
timestamps = [1502744400, 1502830800, 1502917200]
I need to select all timestamp in every interval between i and i+1 of timestamp.
Using Django ORM it's look like:
step = 86400
for ts in timestamps[:-1]:
trackpoint_set.filter(created_at__gte=ts,created_at__lt=ts + step).values('tag').distinct().count()
Because of actually timestamps list is very very longer and table has many of rows, finally i getting 500 time-out
So, my question is, how to for it in ONE raw SQL query join rows and list of values, so it looks like [(1502744400, 650), (1502830800, 1550)...]
Where second first value is timestamp, and the second is count of unique tags in each interval.
First index created_at. Next build query like created_at in (timestamp, timestamp+1). For each timestamp, run the query one by one rather than all at once.

Mysql timestampdiff sum between overlapped intervals

I have the following table structure:
+----+---------------------+---------------------+
| id | created_at | closed |
+----+---------------------+---------------------+
| 1 | 2017-04-03 04:00:00 | 2017-04-03 04:30:00 |
| 2 | 2017-04-03 04:25:00 | 2017-04-03 04:35:00 |
+----+---------------------+---------------------+
In my real SQL query I use timestampdiff to clacualte the diffirence between two dates in timestap field. There is no problem if the ctreated_at and closed_at of all records start in diffirent time intervals, so I would able to get time consumed for all rows as follows:
SELECT SUM(timestampdiff(SECOND, created_at, closed_at)) as TotalTime FROM table
My problem is like the shown table above, the time interval crossing. The above query will result 900 but it I should have 600
I have tried something like:
SELECT timestampdiff(
MINUTE,
a.created_at,
(SELECT max(b.closed) from times as b WHERE b.created_at < a.closed)
) as periods
FROM `times` as a
The result is:
+---------+
| periods |
+---------+
| 35 |
| 10 |
+---------+
Here I want only the first result whuch represnts the net time of the overlapped periods. Using MAX with the previous query should returns the first record but it will lead to neglect any other periods groups added in the futere supposed the table becomes:
+----+---------------------+---------------------+
| id | created_at | closed |
+----+---------------------+---------------------+
| 1 | 2017-04-03 04:00:00 | 2017-04-03 04:30:00 |
| 2 | 2017-04-03 04:25:00 | 2017-04-03 04:35:00 |
| 3 | 2017-04-03 05:00:00 | 2017-04-03 05:15:00 |
+----+---------------------+---------------------+
the above query returns:
+---------+
| periods |
+---------+
| 35 |
| 10 |
| 15 |
+---------+
Again here I don't want the second record because it describes its period which is previously counted in the first record. Indeed I don't know does it possible in MySQL to get (for the example above) only two records or even three records but the second is null, 0, negative value, etc to be distinguished among other really values.
You need to do group by the time on hourly basis and the take difference time for of max.
SELECT max(timestampdiff(
MINUTE,
a.created_at,closed) as periods
FROM `times` as a group by hour(created_at)
Now you will get result as per ur requirement.