Selecting rows with max value in range - php

I have the followng data:
+----+---------+---------------------+-------+
| id | site_id | datetime | views |
+----+---------+---------------------+-------+
| 1 | 1 | 2013-11-01 23:59:59 | 12 |
| 2 | 1 | 2013-11-02 23:59:59 | 15 |
| 3 | 1 | 2013-11-03 23:59:59 | 18 |
| 4 | 1 | 2013-11-04 23:59:59 | 29 |
| 5 | 1 | 2013-11-05 23:59:59 | 38 |
| 6 | 1 | 2013-11-05 12:59:59 | 40 |
| 7 | 1 | 2013-11-06 23:59:59 | 45 |
| 8 | 1 | 2013-11-07 23:59:59 | 49 |
| 9 | 1 | 2013-11-08 23:59:59 | 52 |
| 10 | 2 | 2013-11-04 23:59:59 | 25 |
| 11 | 2 | 2013-11-05 21:59:59 | 42 |
| 12 | 2 | 2013-11-06 23:59:59 | 60 |
| 13 | 2 | 2013-11-07 23:59:59 | 75 |
| 14 | 2 | 2013-11-08 23:59:59 | 86 |
| 15 | 2 | 2013-11-09 23:59:59 | 90 |
| 16 | 2 | 2013-11-10 23:59:59 | 92 |
| 17 | 2 | 2013-11-11 23:42:59 | 98 |
+----+---------+---------------------+-------+
I would pass a day and wish to get the rows with the highest time in the given day or if there`s no records for this site for this day, the last available row in the past.
e.g. for 2013-11-01
+----+---------+---------------------+-------+
| id | site_id | datetime | views |
+----+---------+---------------------+-------+
| 1 | 1 | 2013-11-01 23:59:59 | 12 |
+----+---------+---------------------+-------+
for 2013-11-05
+----+---------+---------------------+-------+
| id | site_id | datetime | views |
+----+---------+---------------------+-------+
| 5 | 1 | 2013-11-05 23:59:59 | 38 |
| 11 | 2 | 2013-11-05 21:59:59 | 42 |
+----+---------+---------------------+-------+
and for 2013-11-10
+----+---------+---------------------+-------+
| id | site_id | datetime | views |
+----+---------+---------------------+-------+
| 9 | 1 | 2013-11-08 23:59:59 | 52 |
| 16 | 2 | 2013-11-10 23:59:59 | 92 |
+----+---------+---------------------+-------+
Thanks in advance.

You can try this:
SELECT a.id,a.site_id,b.maxDate,a.views
FROM table1 a
INNER JOIN (
SELECT site_id ,MAX(datetime) as maxDate
FROM table1
WHERE datetime < DATEYOUWANTTOSEE + INTERVAL 1 DAY
GROUP BY site_id
) b ON a.site_id = b.site_id AND a.datetime = b.maxDate
The inner query will get you the MAX(datetime) for each site_id. Then you join it with your table to get the rest of the information.
sqlfiddle demo

SELECT * FROM <tablename> WHERE datetime = <datetime> ORDER BY datetime DESC LIMIT 2

You data and examples do not really match themselves, nor the description, but what you probably are looking for is this:
Select top 1 *
from table
where date(datetime) <= date(#PARAMETER)
order by datetime desc

I believe this should work:
SELECT SUBSTRING(`datetime`, 1, 10) AS date, MAX(`views`)
FROM table
GROUP BY SUBSTRING(`datetime`, 1, 10)
If you need the id/site_id as well, write it in your post, as it is not clear
SQLFiddle to show you the result:
http://sqlfiddle.com/#!2/e0ccb3/1

Related

create a morris chart in Laravel

so I was able to build a Morris chart following some tutorials, and this is what I've come up with so far
$range = \Carbon\Carbon::now()->subDays(30);
$stats = DB::table('tickets')
->where('created_at', '>=', $range)
->groupBy('date')
->orderBy('date', 'ASC')
->get([
DB::raw('Date(created_at) as date'),
DB::raw('COUNT(*) as value')
])
->toJSON();
OUTPUT
"[{"date":"2018-11-10","value":1},{"date":"2018-11-11","value":1}]"
the thing is I'm trying to get the results by months and ticket status not daily.
js code
Morris.Area({
element: 'morris-area-chart'
, data: data
, xkey: 'date'
, ykeys: ['status']
});
Tickets Table
id|phone_model |cus_name |issue |notes |created_at |updated_at |status
Expected Output
[{"date":"11","tickets":2,"status":1},{"date":"11","tickets":1,"status":2},
{"date":"10","tickets":3,"status":1},{"date":"10","tickets":1,"status":3},]
I tried more than a way to get the results based on months and ticket status but no luck
any help will be appreciated, Thank you.
You can use this query:
$result_arr = \DB::select("SELECT DATE_FORMAT(created_at, '%m') date, status, COUNT(*) count FROM tickets GROUP BY date, status ORDER BY date DESC");
return collect($result_arr)->toJson();
It outputs such a result for example(Output is in mysql console here):
+------+--------+-------+
| date | status | count |
+------+--------+-------+
| 12 | 1 | 1 |
| 12 | 2 | 3 |
| 12 | 4 | 1 |
| 12 | 10 | 7 |
| 11 | 1 | 1 |
| 11 | 2 | 1 |
| 11 | 4 | 1 |
| 10 | 1 | 3 |
| 10 | 2 | 2 |
| 10 | 3 | 1 |
| 10 | 4 | 2 |
| 09 | 1 | 2 |
| 09 | 2 | 7 |
| 09 | 3 | 5 |
| 08 | 1 | 1 |
| 08 | 2 | 1 |
| 08 | 12 | 1 |
| 07 | 1 | 4 |
| 06 | 1 | 1 |
| 06 | 2 | 12 |
| 06 | 3 | 2 |
| 05 | 1 | 1 |
| 05 | 2 | 8 |
| 05 | 11 | 1 |
| 04 | 1 | 2 |
| 04 | 2 | 8 |
| 04 | 10 | 1 |
| 03 | 1 | 2 |
| 02 | 1 | 2 |
| 02 | 2 | 26 |
| 02 | 3 | 1 |
| 02 | 11 | 2 |
| 02 | 12 | 1 |
| 01 | 2 | 21 |
| 01 | 3 | 8 |
| 01 | 10 | 6 |
+------+--------+-------+
36 rows in set (0.00 sec)
Keep in mind that as you want to group the results based on both status & date it does not give you just a row for each date(as you may have multiple statuses), so for each date you may have different values for each status.
See Mysql Docs for more about DATE_FORMAT.

Symfony - Subquery in doctrine2

I have a set of posts on monthly basis. i need an array which contains total records of posts posted in each month (including zeros).
I fail to write it in dql :( Any ideas plz ?
Sample Data:
+----+---------------------+
| id | date |
+----+---------------------+
| 24 | 2012-12-16 16:29:56 |
| 1 | 2013-02-25 14:57:09 |
| 2 | 2013-02-25 14:59:37 |
| 4 | 2013-02-25 15:12:44 |
| 5 | 2013-02-25 15:14:18 |
| 7 | 2013-02-26 11:31:31 |
| 8 | 2013-02-26 11:31:59 |
| 10 | 2013-02-26 11:34:47 |
| 14 | 2013-03-04 04:39:02 |
| 15 | 2013-03-04 05:44:44 |
| 16 | 2013-03-04 05:48:29 |
| 19 | 2013-03-07 15:22:34 |
| 20 | 2013-03-15 12:24:43 |
| 21 | 2013-03-16 16:27:43 |
| 22 | 2013-03-16 16:29:28 |
| 23 | 2013-03-16 16:29:56 |
| 11 | 2013-03-17 11:35:12 |
+----+---------------------+
SQL query:
SELECT count(b.id) as totalRec
FROM (
SELECT 'January' mnth
UNION ALL
SELECT 'February' mnth
UNION ALL
SELECT 'March' mnth
) a
LEFT JOIN post b
ON a.mnth = DATE_FORMAT(b.date, '%M') AND
year(b.date) = '2013' AND
DATE_FORMAT(b.date, '%M') IN ('January', 'February', 'March')
GROUP BY year(b.date)-month(b.date)
ORDER BY b.date ASC
OUTPUT
+----------+
| totalRec |
+----------+
| 0 |
| 7 |
| 9 |
+----------+
Count all posts grouped by month, and filter out the months you want:
SELECT count(*) as totalRec, DATE_FORMAT(b.date, '%m%Y') as month
FROM post b
WHERE month IN('012013', '022013', '032013')
GROUP BY month
ORDER BY b.date ASC
Will result in:
+----------+----------+
| totalRec | month |
+----------+----------+
| 0 | 012013 |
| 7 | 022013 |
| 9 | 032013 |
+----------+----------+

SELECT monthly record form database

mysql> SELECT * FROM con_transactions;
+------+------+---------------------+--------+
| t_id | p_id | date | amount |
+------+------+---------------------+--------+
| 10 | 1 | 2016-02-17 19:24:05 | 1800 |
| 12 | 2 | 2016-02-18 11:40:13 | 200 |
| 17 | 3 | 2016-02-18 11:42:04 | 100 |
| 19 | 4 | 2016-02-18 11:45:43 | 1 |
| 20 | 5 | 2016-02-18 11:45:54 | 999 |
| 21 | 1 | 2016-02-18 11:46:02 | 1500 |
| 41 | 2 | 2016-02-18 17:23:14 | 500 |
| 42 | 3 | 2016-02-18 17:23:14 | 500 |
| 43 | 4 | 2016-02-18 17:23:15 | 500 |
| 44 | 5 | 2016-02-18 17:23:16 | 500 |
| 45 | 1 | 2016-02-18 17:23:16 | 500 |
| 46 | 2 | 2016-02-18 17:23:16 | 500 |
| 47 | 3 | 2016-02-18 17:23:17 | 500 |
| 48 | 4 | 2016-02-18 17:23:17 | 500 |
| 49 | 5 | 2016-02-18 17:23:18 | 500 |
| 50 | 1 | 2016-02-18 17:25:54 | 1000 |
| 51 | 1 | 2016-02-18 17:26:22 | 3000 |
| 52 | 2 | 2016-02-18 17:48:59 | 10 |
| 53 | 1 | 2016-02-18 17:48:59 | 10 |
| 55 | 1 | 2016-02-19 10:20:12 | 1000 |
+------+------+---------------------+--------+
HOW Can I Select current month or last month All Transactions record. All Month are not 30 days. So How can I Select January or other month record with SELECT query. I Try this query
SELECT * FROM con_transactions WHERE date > '2016-01-01 00:00:00' AND date < '2016-02-01 00:00:00';
This is not so smart .
Use month() and year() to directly find any given month of a year.
SELECT * FROM con_transactions WHERE year(date) = 2016 AND month(date) = 1;
One method is to use formats such as as YYYYMM for the date comparison:
SELECT *
FROM con_transactions
WHERE YEAR(date) * 100 + MONTH(date) = YEAR(CURDATE())*100 + MONTH(CURDATE());
However, that has the drawback that MySQL cannot use an index for the WHERE clause. So, another method is a variant of your method but using the first day of the month:
WHERE date >= str_to_date(concat_ws('-', year(curdate()), month(curdate()), '01'), '%Y-%m-%d) and
date < str_to_date(concat_ws('-', year(dateadd(curdate(), interval 1 month)), month(dateadd(curdate(), interval 1 month), '01'), '%Y-%m-%d)

Mysql query for calculating power outage between two time stamps

This is a revised version of my question.
I am currently designing a simple power quality monitoring tool. I have managed to design a MySQL database and populate the table with the voltage status and the corresponding time stamp taken at particular times. Below is my table structure.
+----+---------------------+-------------+
| Id | Time_Stamp | Red_Ph_Volt |
+----+---------------------+-------------+
| 1 | 2015-02-01 17:33:45 | 250.00 |
| 2 | 2015-02-01 18:53:41 | 250.00 |
| 3 | 2015-02-01 18:54:39 | 25.00 |
| 4 | 2015-02-01 18:54:54 | 242.00 |
| 5 | 2015-02-01 18:55:11 | 222.00 |
| 6 | 2015-02-02 21:00:29 | 250.00 |
| 7 | 2015-02-02 21:00:45 | 220.00 |
| 8 | 2015-02-02 21:00:55 | 230.00 |
| 9 | 2015-02-02 21:03:01 | 230.00 |
| 10 | 2015-02-02 21:03:36 | 250.00 |
| 11 | 2015-02-02 21:03:46 | 50.00 |
| 12 | 2015-02-06 17:54:08 | 0.00 |
| 13 | 2015-02-06 23:04:04 | 220.00 |
| 14 | 2015-02-06 23:04:34 | 220.00 |
| 15 | 2015-02-06 23:05:51 | 250.00 |
| 16 | 2015-02-08 16:04:44 | 220.00 |
| 17 | 2015-02-08 16:06:29 | 220.00 |
| 18 | 2015-02-09 09:04:12 | 220.00 |
| 19 | 2015-02-09 10:42:39 | 203.00 |
| 20 | 2015-02-09 19:34:43 | 203.00 |
| 21 | 2015-02-09 21:57:02 | 203.00 |
| 22 | 2015-02-10 09:47:08 | 0.00 |
| 23 | 2015-02-10 11:15:34 | 250.00 |
| 24 | 2015-02-10 11:48:14 | 250.00 |
| 25 | 2015-02-10 13:18:14 | 220.00 |
| 26 | 2015-02-10 18:59:52 | 0.00 |
| 27 | 2015-02-10 22:44:14 | 250.00 |
| 28 | 2015-02-10 22:47:10 | 212.00 |
| 29 | 2015-02-14 00:02:10 | 212.00 |
| 30 | 2015-02-14 00:28:57 | 242.00 |
| 31 | 2015-02-14 00:35:56 | 21.00 |
| 32 | 2015-02-16 12:11:47 | 21.00 |
+----+---------------------+-------------+
32 rows in set (0.02 sec)
Any voltage below 50V is taken as an outage. I want to write a query that queries the table for the TOTAL OUTAGE TIME between 2015-02-01 17:33:45 and 2015-02-14 00:28:57.
Guys, kindly help me on this because I really don’t know how to approach it.
This should work:
SELECT sum(timestampdiff(SECOND, Time_Stamp, (SELECT Time_Stamp
FROM voltage AS V2
WHERE V2.Id > V1.Id
LIMIT 1))) AS T
FROM voltage AS V1
WHERE Red_Ph_Volt <= 50 AND Time_Stamp BETWEEN '2015-02-01 17:33:45' AND '2015-02-14 00:28:57';
I have assumed that a voltage of 50 is also considered as an outage and I have assigned the table name as voltage.
The first step to properly address this kind of queries is to join every row with its previous row.
SELECT *
FROM voltage AS V
LEFT JOIN voltage AS PRV_V ON (PRV_V.Id = V.Id-1)
Now you just have to keep those rows which its previous measure was below 50 and sum their timestamp differences.
SELECT SUM(TIMESTAMPDIFF(SECOND, PRV_V.Time_Stamp, V.Time_Stamp))
FROM voltage AS V
LEFT JOIN voltage AS PRV_V ON (PRV_V.Id = V.Id-1)
WHERE PRV_V.Red_Ph_Volt < 50
AND V.Time_Stamp BETWEEN '2015-02-01 17:33:45' AND '2015-02-14 00:28:57'
EDIT: If your data don't have autoincremental ids or you have gaps between your ids you can still join your measurements with its previous measurement using the timestamp:
SELECT *
FROM voltage AS V
LEFT JOIN voltage AS PRV_V
ON ( PRV_V.Time_Stamp < V.Time_Stamp
AND NOT EXISTS ( SELECT *
FROM voltage
WHERE Time_Stamp > PRV_V.Time_Stamp
AND voltage.Time_Stamp < V.Time_Stamp
)
)

SQL request for several tables and operations in MySQL

I have the following 3 tables: unit, stage, stats.
unit stage
+----+--------+ +----+-------+---------------------+
| id | status | | id |unit_id| date |
+----+--------+ +----+-------+---------------------+
| 1 | 2 | | 1 | 2 | 2013-11-22 00:00:00 |
| 2 | 3 | | 2 | 2 | 2013-11-26 12:00:00 |
| 3 | 3 | | 3 | 3 | 2013-10-11 00:00:00 |
| 4 | 0 | | 4 | 1 | 2013-12-29 00:00:00 |
+----+--------+ +----+-------+---------------------+
stats
+----+----------+---------------------+-------+
| id | stage_id | date | clicks|
+----+----------+---------------------+-------+
| 1 | 1 | 2013-11-22 00:00:00 | 10 |
| 2 | 1 | 2013-11-23 00:00:00 | 20 |
| 3 | 1 | 2013-11-24 00:00:00 | 25 |
| 4 | 2 | 2013-11-26 00:00:00 | 15 |
| 5 | 2 | 2013-11-27 12:00:00 | 21 |
| 6 | 3 | 2013-12-29 00:00:00 | 8 |
+----+----------+---------------------+-------+
I need a request, that will produce the following response:
+---------+---------------------+-----------------------+
| unit.id | stage.min.date | sum(stats.max.clicks) |
+---------+---------------------+-----------------------+
| 2 | 2013-11-22 00:00:00 | 46 |
| 3 | 2013-12-29 00:00:00 | 8 |
+---------+---------------------+-----------------------+
by the following rules:
1) unit.id - show only units with unit.status=3
2) stage.min.date - minimal stage.date for corresponding unit_id
3) sum(stats.max.clicks) - sum of stats.clicks with max dvalues for each stage_id associated with corresponding unit_id. In my example 46 = 25(stage_id=1) + 21(stage_id=2)
The problem is in min.date and sum of clicks - I have no idea how to get it in one query. Definitely it`s not a problem to do it using php code and several requests.
Schema in SQL Fiddle
Thanks in advance.
I just ask myself, why I do this? Your example resonse has an error, and does not match your fiddle... but:
SELECT
cc.unit_id, MIN(cc.date) as stage_min_date , SUM(dd.clicks) as stats_max_clicks
FROM
stage cc
LEFT JOIN (
SELECT
bb.stage_id, bb.clicks
FROM
stats bb LEFT JOIN (
SELECT id, stage_id, MAX(date) AS max_date
FROM stats
GROUP BY stage_id
) aa
ON
aa.max_date = bb.date
WHERE
aa.max_date IS NOT NULL
) dd
ON cc.id = dd.stage_id
LEFT JOIN unit ee
ON ee.id = cc.unit_id
WHERE ee.status = 3
GROUP BY cc.unit_id
...

Categories