Duplication/Updation of data in mysql - mysql

I want to get the sum of the data for every 5 minutes.
I have 15 motes.
for ,suppose in the first 5 minutes only some motes are queried and in the next 5 minutes other some motes are queried.
Now,In the second 5 minutes I need the data of the motes which are not queried in that 5minutes also
ie.,in the first 5minutes moteid's 1,2,3,4,9,12,14 are queried and in the second minutes moteid's 1,5,6,7,9,13,14 are queried.
In the second 5 minutes,I need the data to be updated for the one's which are not queried also.Is it possible to get the data from the previous 5 minutes
moteid2 | 28 | 2012-09-25 17:45:43 | |
moteid4 | 65 | 2012-09-25 17:45:49 | |
moteid3 | 66 | 2012-09-25 17:45:51 | |
moteid6 | 25 | 2012-09-25 17:45:56 | |
moteid5 | 29 | 2012-09-25 17:45:58 | |
moteid7 | 30 | 2012-09-25 17:46:05 | |
moteid4 | 95 | 2012-09-25 17:50:29 | |
moteid6 | 56 | 2012-09-25 17:50:35 | |
moteid5 | 58 | 2012-09-25 17:50:36 | |
moteid4 | 126 | 2012-09-25 17:55:08 |
In the first 5 minutes moteid2, moteid3 are queried, but after that in the next 5minutes they are not queried. Even If they are not being queried i want the same previous queried value to be kept now.

I'm assuming the table name is motes. In this case the following query displays all unique motesid for the records which present in the whole table but were not queried in last 5 minutes:
select distinct m.motesid
from motes m
where not exists (
select *
from motes m1
where
m1.moteid = m.motesid and
m1.date > SUBTIME(CURTIME(), '0:05:00')
)

Related

Rows to columns in MySQL without knowing the rows in advance

I have a MySQL table that looks like this:
+---------+-------------+--------------+-------------+-------------+
| truckNo | excavatorId | times_loaded | litres | litres/time |
+---------+-------------+--------------+-------------+-------------+
| 1 | 345 | 100 | 50 | 0.5 |
+---------+-------------+--------------+-------------+-------------+
| 1 | 275 | 34 | 50 | 1.47 |
+---------+-------------+--------------+-------------+-------------+
| 2 | 275 | 100 | 50 | 0.5 |
+---------+-------------+--------------+-------------+-------------+
In this table, an Excavator loads to any truck one or more times. For example Excavator 345 loaded some material on truck 1 100 times. But Truck 1 was also loaded by excavator 275 some material 34 times. Now I want to group the results per truck, so in the left column I can see the distinct truck and have each excavator as a new column as in the following table:
+--------+---------------------------------+---------------+--------------+
| Truck | Excavators | Total_loads | Total litres | Litres/load |
+--------+-----------+-------+-------------+---------------+--------------+
| | 345 | 275 | | | |
+--------+-----------+-------+-------------+---------------+--------------+
| 1 | 100 | 34 | 134 | 1.95 | 0.01 |
+--------+-----------+-------+-------------+---------------+--------------+
| 2 | | 50 | 50 | 50 | 1 |
+--------+-----------+-------+-------------+---------------+--------------+
The problem is that I never know in advance how many excavators will there be in the table so I know how many columns to make.
Is there any way to do that ? Is it possible is SQL ?
EDIT: Each truck is loaded one or more times by any excavator. So in the result table for example truck no 1 was loaded 100 times by Excavator 345 and 34 times by excavator 275. In total loads you see all loads that were upon truck 1, from all/any excavator which is 134. Same for liters. The litres/load is the division in the result table of Total litres / Total_loads
SQL queries always generate result tables with the columns stated. If you don't know the columns you want to show, you cannot write the query.
Your options:
Select the raw data and construct the result table from that data in your app or Website.
Select the excavators first. Then use your programming language to create a query particularly for those excavators.
Do with one column containing concatenated strings.
Here is #3:
select
truckno,
group_concat('EX(', excavatorid, ')=', times_loaded order by excavatorid) as loads,
sum(times_loaded) as total_loads,
sum(litres) as total_litres,
sum(litres) / sum(times_loaded) as litres_per_load
group by truckno
order by truckno;

Adding one hour to datetime and comparing with present time based on hours and minutes

I have written a query where I am adding one hour to a datetime which is present in database, and comparing that time to the present time based on minutes and hours.
Table structure of upgrades:
id| postid |type |status| counter| datetime | autoreposttime
1 | 139 | M | P | 1 | 2017-04-26 10:49:23 | 60
2 | 140 | M | P | 1 | 2017-04-26 10:49:27 | 60
3 | 141 | M | P | 1 | 2017-04-26 10:49:31 | 60
4 | 142 | M | P | 1 | 2017-04-26 10:49:34 | 60
Table structure of posts:
post_id | locationid | priority_time
81 | 1 | 2017-04-20 18:29:17
82 | 27 | 2017-04-20 18:29:19
85 | 27 | 2017-04-20 18:29:07
Here is my SQL query which I have written in where I want to retrieve rows where datetime + 1 hour is equal to present time.
$posts = DB::table('upgrades')
->join('posts','posts.post_id','=','upgrades.postid')
->where(DB::raw('DATE_FORMAT(DATE_ADD(`upgrades`.`datetime`, INTERVAL 1 HOUR),"%Y-%m-%d %H:%i")'),$datetime)
->select('posts.*','upgrades.*')->get();
I'm getting data as null, and I think there's some problem in the where condition. What is wrong with my query?
One way to do that is to use Carbon. If I understood you correctly, you want result for specified minute, so here's an example:
$time = Carbon::now()->subHour();
$posts = ....
->whereBetween('datetime', [$time->format('Y-m-d H:i:00'), $time->format('Y-m-d H:i:59'])
....
->get();

SQL - select x entries within a timespan

I'm creating a database (in MySQL) with a table of measurements. For each measurement I want to store the DateTime it came in. For showing plots within an app for different intervals (measurements of the day/week/month/year) I want sample the data points I have, so I can return e. g. 30 data points for the whole year as well as for the day/hour. This is the same as done with stock price graphs:
stock price plot for 1 day
vs
stock price plot for 1 month
As you can see, the amount of data points is the same in both pictures.
So how can I select x entries within a timespan in MySQL via SQL?
My data looks like this:
+====+====================+=============+==========+
| id | datetime | temperature | humidity |
+====+====================+=============+==========+
| 1 | 1-15-2016 00:30:00 | 20 | 40 |
+----+--------------------+-------------+----------+
| 2 | 1-15-2016 00:35:00 | 19 | 41 |
+----+--------------------+-------------+----------+
| 3 | 1-15-2016 00:40:00 | 20 | 40 |
+----+--------------------+-------------+----------+
| 4 | 1-15-2016 00:45:00 | 20 | 42 |
+----+--------------------+-------------+----------+
| 5 | 1-15-2016 00:50:00 | 21 | 42 |
+----+--------------------+-------------+----------+
| 6 | 1-15-2016 00:55:00 | 20 | 43 |
+----+--------------------+-------------+----------+
| 7 | 1-15-2016 01:00:00 | 21 | 43 |
+====+====================+=============+==========+
Let's say, I always want two data points (in reality a lot more). So for the last half hour I want the database to return data point 1 and 4, for the last ten minutes I want it to return 6 and 7.
Thanks for helping!
PS: I'm sorry for any errors in my English
OK, assuming a very simple systematic approach, you can get the first and last entry for any defined period:
select *
from table
where mydatetime =
(select
max(mydatetime)
from table
where mydatetime between '2017-03-01' and '2017-03-15'
)
OR mydatetime =
(select
min(mydatetime)
from table
where mydatetime between '2017-03-01' and '2017-03-15'
)
I believe your answer can be found at the following location:
https://stackoverflow.com/a/1891796/7176046
If you are looking to filter out any items not within your date/time your query would use:
Select * from table where Date/Time is (What you want to sort by)

SQL Count Distinct Using Multiple Unique Identifiers

My company ran a series of TV ads and we're measuring the impact by changes in our website traffic. I would like to determine the cost per session we saw generated, based on the cost of each ad.
The trouble is, the table this is referencing has duplicate data, so my currently cost_per_session isn't counting right.
What I have so far:
client_net_cleared = cost of ad
ad_time, media_outlet, & program = combined are a unique identifier for each ad
diff = assumed sessions generated by ad
.
SELECT DISTINCT tadm.timestamp AS ad_time
, tadm.media_outlet AS media_outlet
, tadm.program AS program
, tadm.client_net_cleared AS client_net_cleared
, SUM(tadm.before_ad_sum) AS before_ad_sessions
, SUM(tadm.after_ad_sum) AS after_ad_sessions
, (SUM(tadm.after_ad_sum) - SUM(tadm.before_ad_sum)) AS diff
, CASE WHEN tadm.client_net_cleared = 0 THEN null
WHEN (SUM(tadm.after_ad_sum) - SUM(tadm.before_ad_sum)) <1 THEN null
ELSE (tadm.client_net_cleared/(SUM(tadm.after_ad_sum) - SUM(tadm.before_ad_sum)))
END AS cost_per_session
FROM tableau.km_tv_ad_data_merged tadm
GROUP BY ad_time,media_outlet,program,client_net_cleared
Sample data:
ad_time | media_outlet | program | client_net_cleared | before_ad_sessions | after_add_sessions | diff | cost_per_session
---------------------|---------------|----------------|--------------------|--------------------|--------------------|------|-----------------
2016-12-09 22:55:00 | DIY | | 970 | 55 | 72 | 17 | 57.05
2016-12-11 02:22:00 | E! | E! News | 388 | 25 | 31 | 6 | 64.66
2016-12-19 21:15:00 | Cooking | The Best Thing | 428 | 70 | 97 | 27 | 15.85
2016-12-22 14:01:00 | Oxygen | Next Top Model | 285 | 95 | 148 | 53 | 5.37
2016-12-09 22:55:00 | DIY | | 970 | 55 | 72 | 17 | 57.05
2016-12-04 16:13:00 | Headline News | United Shades | 1698 | 95 | 137 | 42 | 40.42
What I need:
Only count one instance of each ad when calculating cost_per_session.
EDIT: Fixed the query, had a half completed row where I was failing at doing this before asking the question. :)
Get rid of the DISTINCT in SELECT DISTINCT in the first line of your query. It makes no sense in a GROUP BY query.
If your rows are entirely duplicate, try deduplicating the table before you put it into the GROUP BY grinder by replacing
FROM tableau.km_tv_ad_data_merged tadm
with
FROM ( SELECT DISTINCT timestamp, media_outlet, program,
client_net_cleared,
before_ad_sum, after_ad_sum
FROM tableau.km_tv_ad_data_merged
) tadm

Selecting max price from every 5 rows

I've been trying and trying and haven't been able to figure this out.
In stock charts that have Open, High, Low, Close, you can always chart every minute, 5 min, 10 min, hour, etc. I have data for every minute and I'm trying to select out the Open, High, Low, Close from that minute-by-minute data, but for every 5 minutes.
I have data similar to this:
__________________________________________________
| Date | TIME | TICKER | Open | High | Low | Close |
| 20121203 | 090000 | QQQQ | 23.54 | 24.12 | 23.01 | 23.24 |
| 20121203 | 090100 | QQQQ | 23.24 | 24.14 | 22.98 | 24.13 |
| 20121203 | 090200 | QQQQ | 24.13 | 25.88 | 23.75 | 25.81 |
| 20121203 | 090300 | QQQQ | 25.81 | 25.83 | 24.63 | 24.99 |
| 20121203 | 090400 | QQQQ | 24.99 | 25.21 | 23.89 | 24.12 |
| 20121203 | 090500 | QQQQ | 24.12 | 24.19 | 21.94 | 22.03 |
| 20121203 | 090600 | QQQQ | 22.03 | 22.97 | 20.68 | 21.44 |
| 20121203 | 090700 | QQQQ | 21.44 | 24.06 | 19.32 | 23.56 |
| 20121203 | 090800 | QQQQ | 23.56 | 25.48 | 23.07 | 25.01 |
| 20121203 | 090900 | QQQQ | 25.01 | 28.00 | 24.18 | 27.21 |
| 20121203 | 091000 | QQQQ | 27.21 | 27.55 | 24.31 | 24.31 |
I need to grab the max(high) for the rows that have a time >= 090000 (that's 9 a.m.) 09 hours 00 minutes 00 seconds.
Similar to this, I need min(low), and then I'll grab the close price when time is 090400 because I'm getting every 5 minutes. I could also use the open of the next 5 minute increment, so that's flexible.
I've used nested SELECT statements, multiple joins, etc. The problem is that the MySQL execution time is about 1 second per row returned. That's crazy slow when you figure there are 12 rows per hour (60 minutes / 5 minutes = 12), and then because I'm actually doing FOREX, the trading is around the clock, so 24 hours. That gives me 288 per day, or just under 5 minutes per day. To do 1 year of data (~ 250 trading days) would be about 20 hours. There has to be a faster way.
I've got some solutions for this with the ID being continuous, and though that might be easiest, I'm not 100% sure my data would be correct in doing that. The reason why is that on Fridays the trading day ends at normal business hours in NY and opens up with the first trading in Tokyo (about mid-afternoon in the United States).
I've looked at GROUP BY, but I'm not sure how I can group the data to get a group of 5 where the time is within 5 minutes of each 5 minute group.
Thanks for your thoughts and discussion.
Jarod
This should show max(high) and min(low) for every 5 minutes
SELECT Max(high),
Min(low)
FROM tbl
GROUP BY ROUND(Unix_timestamp(Date(Concat(`date`, `time`))) / ( 5 * 60 ))
In the Group by clause we concat your date time column. So it forms something like 20121203090000. This is one the format that is recognized as date in mysql. So we pass it to date() function. Then its converted to UNIX_TIMESTAMP. Its divided by 5 mins timespan. The result will be a float value. But we require same value for a specific time span. Hence the ROUND(). It makes the floating value to the nearest integer. To understand how its working run this query.
SELECT high,
low
Unix_timestamp(Date(Concat(`date`, `time`))) / ( 5 * 60 ) `5-min span`
ROUND(Unix_timestamp(Date(Concat(`date`, `time`))) / ( 5 * 60 )) `5-min span rounded`
FROM tbl
try this:
SELECT CONCAT(DATE,SUBSTRING(Time,1,2),"["
,IF(SUBSTRING(Time,4,1)<5,CONCAT(SUBSTRING(Time,3,1),"0"),CONCAT(SUBSTRING(Time,3,1),"5"))
,"-"
,IF(SUBSTRING(Time,4,1)<5,CONCAT(SUBSTRING(Time,3,1),"5"),CONCAT(SUBSTRING(Time,3,1)+1,"0"))
,"]") AS timeStr ,MAX(High) ,MIN(LOW) FROM tb1 GROUP BY timeStr;
http://sqlfiddle.com/#!2/6b748/1