copy specific row from multiple table into another table in sql - mysql

I want to copy a specific row from tables temperature, rules and schedule to stats table.
In temperature table, I want the latest temperature which is 18.6
mysql> SELECT * FROM currenttemp ORDER BY `timestamp` DESC limit 10 ;
+---------------------+-----------------+-------------+----------+----------+
| timestamp | sensor | currenttemp | humidity | pressure |
+---------------------+-----------------+-------------+----------+----------+
| 2017-03-25 15:28:03 | sensor-1stFloor | 18.6 | 49.85 | 1021.26 |
| 2017-03-25 15:27:03 | sensor-1stFloor | 18.7 | 49.81 | 1021.26 |
| 2017-03-25 15:26:03 | sensor-1stFloor | 18.8 | 49.82 | 1021.26 |
| 2017-03-25 15:25:03 | sensor-1stFloor | 18.9 | 49.85 | 1021.22 |
| 2017-03-25 15:24:03 | sensor-1stFloor | 18.99 | 49.83 | 1021.21 |
| 2017-03-25 15:23:03 | sensor-1stFloor | 18.61 | 49.85 | 1021.18 |
| 2017-03-25 15:22:02 | sensor-1stFloor | 18.62 | 49.8 | 1021.3 |
| 2017-03-25 15:21:02 | sensor-1stFloor | 18.63 | 49.82 | 1021.39 |
| 2017-03-25 15:20:03 | sensor-1stFloor | 18.61 | 49.82 | 1021.28 |
| 2017-03-25 15:19:03 | sensor-1stFloor | 18.62 | 49.82 | 1021.37 |
+---------------------+-----------------+-------------+----------+----------+
In rules table, I want the targettemp for schedule 4 which is 40
mysql> SELECT * FROM rules limit 10 ;
+----+----------+--------+------------+
| id | schedule | sensor | targettemp |
+----+----------+--------+------------+
| 1 | 4 | 1 | 40 |
| 2 | 5 | 1 | 5 |
+----+----------+--------+------------+
In schedule table, I want the endtime for id 4 which is 10:00:00
mysql> SELECT * FROM schedules limit 10 ;
+----+--------------+-----------+--------------+-----------+----------+---------+------------+--------+
| id | friendlyname | dayofweek | pretimestart | timestart | endtime | enabled | targettemp | sensor |
+----+--------------+-----------+--------------+-----------+----------+---------+------------+--------+
| 4 | test | 1111110 | 00:00:00 | 00:00:00 | 10:00:00 | 1 | 30 | 1 |
| 5 | sun | 0000001 | 00:00:00 | 00:00:00 | 20:00:00 | 0 | 0 | |
+----+--------------+-----------+--------------+-----------+----------+---------+------------+--------+
I then want to insert these data to the stats table
currenttemp which is 18.6
targettemp for schedule 4 which is 40
endtime for id 4 which is 10:00:00
the timestamp is done automatically
state will be between ON and OFF
please look at the 1st row in stats table as example from the data copied from the above tables.
mysql> SELECT * FROM stats limit 10 ;
+---------------------+-------------+------------+----------+-------+
| timestamp | currenttemp | targettemp | endtime | state |
+---------------------+-------------+------------+----------+-------+
| 2017-03-25 15:41:46 | 18.6 | 40 | 10:00:00 | OFF |
| 2017-03-19 16:53:05 | 16.83 | 5 | 00:00:00 | OFF |
| 2017-03-19 16:54:14 | 16.83 | 40 | 00:00:00 | ON |
| 2017-03-19 20:04:07 | 16.58 | 40 | 00:00:00 | ON |
| 2017-03-19 20:04:15 | 16.58 | 5 | 00:00:00 | OFF |
| 2017-03-19 20:06:29 | 16.58 | 5 | 00:00:00 | OFF |
| 2017-03-19 20:34:28 | 16.54 | 5 | 00:00:00 | OFF |
| 2017-03-19 20:34:56 | 16.54 | 5 | 00:00:00 | OFF |
| 2017-03-19 20:35:26 | 16.54 | 40 | 00:00:00 | ON |
| 2017-03-19 20:38:05 | 16.54 | 40 | 00:00:00 | ON |
+---------------------+-------------+------------+----------+-------+
I will have 2 queries. One with the state OFF and one with the state ON.

Your question is unclear because the relationship between temperature and the other tables is unclear. Let me assume that there is a join key to schedules. If so, the query you want would look something like this:
INSERT INTO stats (currenttemp, targettemp, endtime)
SELECT t.temperature, r.targettemp, s.timeend
FROM schedules s INNER JOIN
rules r
ON s.id = r.schedule INNER JOIN
temperature t
ON t.schedule = s.id
WHERE s.id = 4 AND
t.timestamp = (SELECT MAX(t2.timestamp)
FROM temperature t2
WHERE t2.schedule = t.schedule
);

this seems to work
INSERT INTO stats (currenttemp,targettemp,endtime,state)
SELECT
temperature,r.targettemp,s.timeend,'OFF'
FROM
schedules s
INNER JOIN rules r
ON s.id = r.schedule
INNER JOIN temperature
WHERE timestamp = (SELECT MAX(timestamp) FROM temperature)
AND s.id = 4
i can see now in my stats table
mysql> SELECT * FROM stats limit 10 ;
+---------------------+-------------+------------+----------+-------+
| timestamp | currenttemp | targettemp | endtime | state |
+---------------------+-------------+------------+----------+-------+
| 2017-04-06 17:58:05 | 19.53 | 40 | 10:00:00 | OFF |
+---------------------+-------------+------------+----------+-------+

Related

MYSQL - How may i subtract two columns on two different rows, on the same table?

I have a select taht brings the result like this:
+-----------+------------+--------------+
| parking_id| start_time | end_time |
+-----------+------------+--------------+
| 38 | 09:15:00 | 10:32:00 |
| 57 | 11:45:00 | 13:21:00 |
| 33 | 14:40:00 | 16:35:00 |
| 15 | 17:13:00 | 19:15:00 |
| 68 | 20:54:00 | NULL |
+-----------+------------+--------------+
As you can see the IDs dont follow a linear order, but wat i really need is a select that brings me the time between the new start_time and end_time for the last inserted , that follows this non linear order, so i need a select that brings me this:
+-----------+------------+--------------+----------------+
| parking_id| start_time | end_time | time_btw_parks |
+-----------+------------+--------------+----------------+
| 38 | 09:15:00 | 10:32:00 | NULL |
| 57 | 11:45:00 | 13:21:00 | 01:13:00 |
| 33 | 14:40:00 | 16:35:00 | 01:19:00 |
| 15 | 17:13:00 | 19:15:00 | 00:38:00 |
| 68 | 20:54:00 | NULL | 01:39:00 |
+-----------+------------+--------------+----------------+
Doesn't have to necessary be select query. Anything that solves it would help.
For this sample data you can use timediff() function:
select t.parking_id, t.start_time, t.end_time,
timediff(t.start_time, max(tt.end_time)) time_btw_parks
from tablename t left join tablename tt
on t.start_time > tt.end_time
group by t.parking_id, t.start_time, t.end_time
order by t.start_time
See the demo.
Results:
| parking_id | start_time | end_time | time_btw_parks |
| ---------- | ---------- | -------- | -------------- |
| 38 | 09:15:00 | 10:32:00 | |
| 57 | 11:45:00 | 13:21:00 | 01:13:00 |
| 33 | 14:40:00 | 16:35:00 | 01:19:00 |
| 15 | 17:13:00 | 19:15:00 | 00:38:00 |
| 68 | 20:54:00 | | 01:39:00 |

how to search closest date in the table after a given date using hql

I want to search closest dates and its data records from the table after a given date using hql.
I've database table named timetable
+-------------+------------+--------------------+---------------------+----------+
| timeTableId | date | hospital | time | doctorId |
+-------------+------------+--------------------+---------------------+----------+
| 1 | 2017.03.02 | Medix Care,Marad | 9.30 am to 10.30 am | 3 |
| 2 | 2017.03.02 | Medix Care,Marad | 3.30 to 5.30 | 3 |
| 3 | 2012.03.02 | Medix Care,Marad | 03.30 to 04.30 | 2 |
| 4 | 2017.05.03 | Medix Care,Marad | 11.25 to 12.25 | 5 |
| 5 | 2012.03.20 | Medix Care,Marad | 12.30 to 01.30 | 4 |
| 6 | 2012.12.12 | Medix Care,Gacko | 12.30 to 02.25 | 6 |
| 7 | 2012.12.12 | Medix Care,Marad | 12.30 to 02.25 | 10 |
| 8 | 2017.06.07 | Medix Care,Marad | 11.30 to 12.30 | 1 |
+-------------+------------+--------------------+---------------------+----------+
How to write hql query for this.
Try this -
SELECT MIN(date)
FROM (SELECT date
FROM timetable
WHERE GIVEN_DATE >= date) X

MySQL: Get everyday incremental data

I want to fetch the data from Table based on date but in an incremental way.
Suppose I have data like this which is grouped by date
| DATE | Count |
| 2015-06-23 | 10 |
| 2015-06-24 | 8 |
| 2015-06-25 | 6 |
| 2015-06-26 | 3 |
| 2015-06-27 | 2 |
| 2015-06-29 | 2 |
| 2015-06-30 | 3 |
| 2015-07-01 | 1 |
| 2015-07-02 | 3 |
| 2015-07-03 | 4 |
So the result should come like this
| DATE | Count| Sum|
| 2015-06-23 | 10 | 10 |
| 2015-06-24 | 8 | 18 |
| 2015-06-25 | 6 | 24 |
| 2015-06-26 | 3 | 27 |
| 2015-06-27 | 2 | 29 |
| 2015-06-29 | 2 | 31 |
| 2015-06-30 | 3 | 34 |
| 2015-07-01 | 1 | 35 |
| 2015-07-02 | 3 | 38 |
| 2015-07-03 | 4 | 42 |
You would join every other previous date on that date, and then sum the count on that
If you give me your table structure, I can make it run.
id, name, date_joined
SELECT counts.theCount, sum(counts.theCount), table.date_joined
FROM yourTable
LEFT JOIN
(SELECT count(*) as theCount, table.date_joined
FROM yourTable
GROUP BY table.date_joined
) as counts
ON
yourTable.date_joined> counts.date_joined
GROUP BY yourTable.date_joined

MySQL SUM() returning spurious (?) values

Despite spending an hour on this, the solution is eluding me still. I have a complex-ish query that is returning incorrect data for the SUM(). Yet, when I strip it down to the barest form, it outputs the correct data. But why and fix, I cannot figure out.
The Problem
SELECT po.*, SUM( poo.material_qty ) AS total_items_ordered, suppliers.supplier_name
FROM `purchase_orders` po
LEFT JOIN purchase_orders_items poo ON poo.poid = po.poid
LEFT JOIN suppliers ON suppliers.supplier_id = po.supplier_id
LEFT JOIN materials_batch mb ON mb.purchase_order_no = po.poid
WHERE po_status NOT
IN (
'Fulfilled', 'Cancelled'
)
AND batch_status NOT
IN (
'Arrived', 'Cancelled', 'Refused', 'Missing', 'Damaged', 'Completed'
)
GROUP BY po.poid
ORDER BY date_expected ASC
Provides wildly incorrect data for 'total_items_ordered'.
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
| poid | date_raised | date_expected | supplier_id | job_id | job_item_id | ref_no | sub_total | VAT | total | userid | DN | manual | po_status | total_items_ordered | supplier_name |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
| 15571 | 2014-06-24 13:32:55 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 14850.10 | 2970.02 | 17820.12 | 1 | | N | Raised | 545 | John Parker & Son Ltd |
| 15572 | 2014-06-24 13:33:26 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 997.80 | 199.56 | 1197.36 | 1 | | N | Raised | 80 | John Parker & Son Ltd |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+---------------------+-----------------------+
2 rows in set (0.00 sec)
And yet, when I strip all the complexities out of the query and run the raw SUM(), the value is correct:
mysql> SELECT poid, SUM(material_qty) AS total_items_ordered FROM `purchase_orders_items` GROUP BY poid;
+-------+---------------------+
| poid | total_items_ordered |
+-------+---------------------+
| 15571 | 109 |
| 15572 | 20 |
+-------+---------------------+
2 rows in set (0.00 sec)
Can anyone shed any light on where I'm going wrong here?? I've included all the test table content below just in case you can spot something I've missed. Thank you!
Data Example
mysql> SELECT * FROM purchase_orders;
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
| poid | date_raised | date_expected | supplier_id | job_id | job_item_id | ref_no | sub_total | VAT | total | userid | DN | manual | po_status |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
| 15571 | 2014-06-24 13:32:55 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 14850.10 | 2970.02 | 17820.12 | 1 | | N | Raised |
| 15572 | 2014-06-24 13:33:26 | 2014-06-25 00:00:00 | 1 | 0 | 0 | | 997.80 | 199.56 | 1197.36 | 1 | | N | Raised |
+-------+---------------------+---------------------+-------------+--------+-------------+--------+-----------+---------+----------+--------+----+--------+-----------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM purchase_orders_items;
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
| poi_id | poid | material_id | material_qty | material_price | material_sku | material_name |
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
| 1 | 15571 | 2 | 3 | 100.00 | PKS275282 | 406x140 White Universal Beam (S355) |
| 2 | 15571 | 5 | 10 | 17.40 | 118-64-44 | Test Item (S275) |
| 3 | 15571 | 8 | 1 | 9984.50 | 113-64-21 | A really really really big universal beam (S355) |
| 4 | 15571 | 9 | 77 | 10.00 | 12345 | A thing |
| 5 | 15571 | 10 | 18 | 201.20 | 12-34-56 | 102x230 Narrow Beam (S355) |
| 6 | 15572 | 2 | 6 | 100.00 | PKS275282 | 406x140 White Universal Beam (S355) |
| 7 | 15572 | 5 | 9 | 17.40 | 118-64-44 | Test Item (S275) |
| 8 | 15572 | 9 | 4 | 10.00 | 12345 | A thing |
| 9 | 15572 | 10 | 1 | 201.20 | 12-34-56 | 102x230 Narrow Beam (S355) |
+--------+-------+-------------+--------------+----------------+--------------+--------------------------------------------------+
9 rows in set (0.00 sec)
mysql> SELECT * FROM suppliers;
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
| supplier_id | supplier_name | supplier_telephone | supplier_fax | supplier_added_date | supplier_added_by | supplier_last_updated | supplier_last_updated_by | supplier_assessed | supplier_approved_by |
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
| 1 | John Parker & Son Ltd | 01227 783333 | 0800 521932 | 2014-05-04 15:57:43 | 1 | 2014-06-05 16:38:23 | 1 | 2014-05-04 15:57:43 | 2 |
| 2 | Superior Glass Ltd. | 01825 764766 | 01825 767699 | 2014-05-04 17:48:38 | 1 | 2014-06-04 20:14:16 | 1 | 2014-05-04 17:48:38 | 3 |
| 3 | DTS Origins Ltd. | 01283 3283029 | 01928 303494 | 2014-05-04 17:51:57 | 1 | 2014-05-04 17:53:08 | 1 | 2014-05-04 17:51:57 | 2 |
+-------------+-----------------------+--------------------+--------------+---------------------+-------------------+-----------------------+--------------------------+---------------------+----------------------+
3 rows in set (0.00 sec)
mysql> SELECT * FROM materials_batch;
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
| material_batch_id | poiid | rcvd_date | purchase_order_no | delivery_note_no | qty | rcvd_by | dn_scanned | material_id | supplier_id | batch_status |
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
| 1 | 1 | 0000-00-00 00:00:00 | 15571 | | 3 | 0 | No | 2 | 1 | Ordered |
| 2 | 2 | 0000-00-00 00:00:00 | 15571 | | 10 | 0 | No | 5 | 1 | Ordered |
| 3 | 3 | 0000-00-00 00:00:00 | 15571 | | 1 | 0 | No | 8 | 1 | Ordered |
| 4 | 4 | 0000-00-00 00:00:00 | 15571 | | 77 | 0 | No | 9 | 1 | Ordered |
| 5 | 5 | 0000-00-00 00:00:00 | 15571 | | 18 | 0 | No | 10 | 1 | Ordered |
| 6 | 6 | 0000-00-00 00:00:00 | 15572 | | 6 | 0 | No | 2 | 1 | Ordered |
| 7 | 7 | 0000-00-00 00:00:00 | 15572 | | 9 | 0 | No | 5 | 1 | Ordered |
| 8 | 8 | 0000-00-00 00:00:00 | 15572 | | 4 | 0 | No | 9 | 1 | Ordered |
| 9 | 9 | 0000-00-00 00:00:00 | 15572 | | 1 | 0 | No | 10 | 1 | Ordered |
+-------------------+-------+---------------------+-------------------+------------------+-----+---------+------------+-------------+-------------+--------------+
The reason for the wrong results should be clear when you leave out the GROUP BY from your query. For each table you JOIN, the number of returned rows is multiplied by the number of rows found by the JOIN.
As the materials_batch table contains multiple entries per order, the resulting total_items_ordered is multiplied by 5 for order number 15571, and its multiplied by 4 for order number 15572.
Try the following:
SELECT
po.*,
(
SELECT SUM(poo.material_qty)
FROM purchase_orders_items poo
WHERE poo.poid = po.poid
) AS total_items_ordered,
suppliers.supplier_name
FROM `purchase_orders` po
LEFT JOIN suppliers ON suppliers.supplier_id = po.supplier_id
LEFT JOIN materials_batch mb ON mb.purchase_order_no = po.poid
WHERE po_status NOT
IN (
'Fulfilled', 'Cancelled'
)
AND batch_status NOT
IN (
'Arrived', 'Cancelled', 'Refused', 'Missing', 'Damaged', 'Completed'
)
GROUP BY po.poid
ORDER BY date_expected ASC

MySQL order by rand() grouped by day

Is it possible to get random items inside the same day?
For example:
+----+---------------------+
| id | md |
+----+---------------------+
| 1 | 2010-06-27 11:26:01 |
| 2 | 2010-06-27 11:28:20 |
| 3 | 2010-06-27 11:29:46 |
| 4 | 2010-06-27 11:30:50 |
| 5 | 2010-06-27 12:20:56 |
| 6 | 2010-06-27 12:27:42 |
| 7 | 2010-06-27 15:14:05 |
| 8 | 2010-07-06 01:53:33 |
| 9 | 2010-07-06 01:52:52 |
+----+---------------------+
I want to pick random items inside the same day, but at same time i want it ordered by date desc. Something like this:
+----+---------------------+
| id | md |
+----+---------------------+
| 8 | 2010-07-06 01:53:33 | random block
| 9 | 2010-07-06 01:52:52 |
| 2 | 2010-06-27 11:28:20 | random block
| 4 | 2010-06-27 11:30:50 |
| 1 | 2010-06-27 11:26:01 |
| 6 | 2010-06-27 12:27:42 |
| 3 | 2010-06-27 11:29:46 |
| 5 | 2010-06-27 12:20:56 |
| 7 | 2010-06-27 15:14:05 |
+----+---------------------+
No idea how to start or if this is even possible since order by rand() won't accept grouping.
really simple:
SELECT *
FROM tbl
ORDER BY md DESC, RAND()
Probably not very efficient, but try
select * from (select * from tbl order by rand()) as t group by date(md)
If I have understood your question correctly, this should do the trick:
SELECT * FROM table1 ORDER BY DATE(md) DESC, RAND();
Example:
DROP TABLE IF EXISTS `table1`;
CREATE TABLE `table1` (
`id` int(11) NOT NULL auto_increment,
`md` DATETIME,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
DELIMITER //
DROP PROCEDURE IF EXISTS autofill//
CREATE PROCEDURE autofill()
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < 50 DO
INSERT INTO table1 (md) VALUES (DATE_ADD(NOW(), INTERVAL FLOOR(RAND() * 1000) HOUR));
SET i = i + 1;
END WHILE;
END;
//
DELIMITER ;
CALL autofill();
SELECT * FROM table1 ORDER BY DATE(md) DESC, RAND();
+----+---------------------+
| id | md |
+----+---------------------+
| 8 | 2010-08-16 13:46:04 |
| 16 | 2010-08-15 19:46:05 |
| 47 | 2010-08-15 18:46:06 |
| 25 | 2010-08-15 15:46:05 |
| 33 | 2010-08-15 09:46:05 |
| 3 | 2010-08-14 20:46:04 |
| 45 | 2010-08-13 03:46:06 |
| 17 | 2010-08-12 13:46:05 |
| 12 | 2010-08-12 06:46:05 |
| 7 | 2010-08-12 15:46:04 |
| 37 | 2010-08-12 14:46:05 |
| 40 | 2010-08-10 05:46:06 |
| 13 | 2010-08-09 10:46:05 |
| 4 | 2010-08-09 00:46:04 |
| 1 | 2010-08-06 12:46:04 |
| 28 | 2010-08-02 23:46:05 |
| 15 | 2010-08-02 10:46:05 |
| 2 | 2010-08-02 01:46:04 |
| 38 | 2010-07-31 13:46:06 |
| 27 | 2010-07-31 04:46:05 |
| 30 | 2010-07-31 03:46:05 |
| 22 | 2010-07-31 08:46:05 |
| 50 | 2010-07-30 05:46:06 |
| 11 | 2010-07-28 13:46:05 |
| 18 | 2010-07-28 21:46:05 |
| 29 | 2010-07-27 23:46:05 |
| 35 | 2010-07-27 11:46:05 |
| 6 | 2010-07-26 20:46:04 |
| 20 | 2010-07-25 03:46:05 |
| 31 | 2010-07-23 07:46:05 |
| 14 | 2010-07-23 23:46:05 |
| 23 | 2010-07-23 10:46:05 |
| 48 | 2010-07-23 17:46:06 |
| 42 | 2010-07-21 03:46:06 |
| 39 | 2010-07-20 05:46:06 |
| 36 | 2010-07-18 05:46:05 |
| 10 | 2010-07-17 01:46:05 |
| 32 | 2010-07-16 06:46:05 |
| 9 | 2010-07-16 15:46:04 |
| 24 | 2010-07-16 10:46:05 |
| 43 | 2010-07-16 09:46:06 |
| 5 | 2010-07-14 01:46:04 |
| 21 | 2010-07-14 08:46:05 |
| 49 | 2010-07-13 07:46:06 |
| 41 | 2010-07-13 15:46:06 |
| 46 | 2010-07-12 04:46:06 |
| 44 | 2010-07-11 16:46:06 |
| 26 | 2010-07-10 14:46:05 |
| 34 | 2010-07-09 16:46:05 |
| 19 | 2010-07-07 01:46:05 |
+----+---------------------+
You can use a WHERE clause...
WHERE date = 'insert date' ORDER BY rand() LIMIT 1`
Then just use PHP to insert whatever the date is into the string there for each date.
Or to use only one MySQL query, simply order them by date descending and pull them all out using PHP...
while ($item = mysql_fetch_array($query)):
// process to figure out the date (I'm sure you can do that)
$mydates[$date][] = $id; // add that ID to that date array
endwhile;
foreach ($mydates as $date):
$key = array_rand($date);
endforeach;