MySql query extract value with between syntax - mysql

These are my rows in MySql database table:
+------------+----------+-------------+
| theDate | theHour | theUserCode |
+------------+----------+-------------+
| 2015-11-16 | 06:30:00 | XX2111905 |
| 2015-11-16 | 21:30:37 | XX2112111 |
| 2015-11-16 | 22:21:29 | XX2112111 |
| 2015-11-16 | 17:15:18 | XX2142122 |
| 2015-11-16 | 04:22:13 | XX2146905 |
| 2015-11-16 | 15:15:00 | XX2146905 |
| 2015-11-16 | 21:26:00 | XX2148516 |
+------------+----------+-------------+
7 rows in set
I need extract from this table the rows with theHour between 15:00:00 and 03:00:00.
I have tried this Sql query but in output I have the Empty set.
SELECT
theDate,
theHour,
theUserCode
FROM
`tblUserRegistered`
WHERE
theDate BETWEEN DATE_SUB('2015-11-16', INTERVAL 1 DAY)
AND '2015-11-16'
AND theHour BETWEEN '15:00:00'
AND '03:00:00'
ORDER BY
theUserCode,
theDate,
theHour ASC;
Please help me, thank you so much in advance.

I used the HOUR() function in my query below to handle the check by hour. This query will include records later than 3pm (15 hours), or earlier than 3am (03 hours).
SELECT theDate, theHour, theUserCode
FROM tblUserRegistered
WHERE theDate BETWEEN DATE_SUB('2015-11-16', INTERVAL 1 DAY) AND '2015-11-16'
AND (HOUR(theHour) >= 15 OR HOUR(theHour) <= 3)
ORDER BY theUserCode, theDate, theHour ASC

Related

MySql Delete Data older than 1 month but leave one entry per week and id (the one with the lowest value)

This is the table I am working with:
+---------------------+-----------
| Field | Type |
+---------------------+--------------+
| ID | binary(17) |
| MiscSensor_ID | binary(17) |
| rawValue | varchar(100) |
| RawValueUnitType_ID | int |
| timestamp | timestamp |
+---------------------+--------------+
Now my goal is to implement an event which deletes all entries older than a month BUT for each week I want to leave one entry per MiscSensor_ID (the one with the lowest rawValue).
I am this far:
CREATE EVENT delete_old_miscsensordatahistory
ON SCHEDULE EVERY 1 DAY
STARTS CURRENT_DATE + INTERVAL 1 DAY
DO
DELETE
FROM history
WHERE TIMESTAMPDIFF(DAY, timestamp,NOW()) > 31;
I need to do something like: delete if (value > minvalue) and group it in by MiscSensor_ID and 7 day periods but i am stuck right now on how to do that.
Any help would be much appreciated.
You can try using the ROW_NUMBER window function to match the rows which you don't want to delete. Records having row number equal to 1 will be those rows with the minimum "rawValue" for each combination of (week, sensorId).
WITH cte AS (
SELECT *, ROW_NUMBER() OVER(
PARTITION BY MiscSensorId, WEEK(timestamp)
ORDER BY rawValue ) AS rn
FROM history
WHERE TIMESTAMPDIFF(DAY, timestamp,NOW()) > 31
)
DELETE
FROM history
INNER JOIN cte
ON history.ID = cte.ID
WHERE rn > 1;
This is how i implemented the event right now:
CREATE EVENT delete_old_miscsensordatahistory
ON SCHEDULE EVERY 1 DAY
STARTS CURRENT_DATE + INTERVAL 1 DAY
DO
WITH cte AS (
SELECT *, ROW_NUMBER() OVER(
PARTITION BY MiscSensor_ID, WEEK(timestamp)
ORDER BY CAST(rawValue AS SIGNED) ) AS rn
FROM MiscSensorDataHistory
WHERE TIMESTAMPDIFF(DAY, timestamp,NOW()) > 31
)
DELETE MiscSensorDataHistory
FROM MiscSensorDataHistory
INNER JOIN cte
ON cte.ID = MiscSensorDataHistory.ID
WHERE rn > 1
Testing my method I found out that there are still entries with the same MiscSensor_ID and less than 7 days apart:
| 0x3939333133303037343939353436393032 | 0x3439303031303031303730303030303535 | 554 | 30 | 2022-02-17 23:09:21 |
| 0x3939333133303037343939313631333039 | 0x3439303031303031303730303030303535 | 554 | 30 | 2022-02-06 16:52:48 |
| 0x3939333133303037343938383835353239 | 0x3439303031303031303730303030303535 | 553 | 30 | 2022-01-30 08:21:55 |
| 0x3939333133303037343938383639333436 | 0x3439303031303031303730303030303535 | 554 | 30 | 2022-01-29 22:48:06 |
| 0x3939333133303037343937303734353537 | 0x3439303031303031303730303030303535 | 444 | 30 | 2021-12-26 06:12:07 |
| 0x3939333133303037343937303530363738 | 0x3439303031303031303730303030303535 | 446 | 30 | 2021-12-25 21:53:03 |
| 0x3939333133303037343936333034343238 | 0x3439303031303031303730303030303535 | 0 | 30 | 2021-12-14 13:08:04 |
| 0x3939333133303037343935393934303832 | 0x3439303031303031303730303030303535 | 415 | 30 | 2021-12-08 12:56:43
Any suggestions would be much appreciated.

How to get records for last 3 months while grouping by each month

Please how do I sum records in my MySQL table for the last 3 months but group them by month.
I want something like this:
select SUM(amount) from table where.....
group by month
I am doing the below but it is not returning any results
SELECT MONTHNAME(a.created_at) MONTH, YEAR(a.created_at) YEAR, SUM(a.credit) as credit, SUM(a.debit)
FROM telco_transactions AS a
WHERE a.telco_id = '1' and DATE(a.created_at) = DATE_ADD(NOW(), INTERVAL -3 MONTH)
GROUP BY MONTHNAME(a.created_at), YEAR(a.created_at);
select T.date_time, SUM(T.amount) from (
-> select * from TEST_TABLE where date_time >= DATE_ADD(CURDATE(), INTERVAL -3 MONTH) and date_time <= CURDATE())
-> as T GROUP BY MONTH(T.date_time);
The table test_table looks like
+------------+--------+
| date_time | amount |
+------------+--------+
| 2017-12-24 | 30 |
| 2017-09-24 | 30 |
| 2017-12-04 | 30 |
| 2017-11-24 | 30 |
| 2017-11-09 | 30 |
| 2017-10-24 | 30 |
+------------+--------+
and the output of the query looks like
+------------+---------------+
| date_time | SUM(T.amount) |
+------------+---------------+
| 2017-09-24 | 30 |
| 2017-10-24 | 30 |
| 2017-11-24 | 60 |
| 2017-12-24 | 60 |
+------------+---------------+
I would try this:
SELECT SUM(records)
FROM TABLE_NAME
WHERE Date_Column >= DATEADD(MONTH, -3, GETDATE())
GROUP BY DATEPART(MONTH, Date_Column)
I found a answer
SELECT MONTHNAME(a.created_at) as tmonth, YEAR(a.created_at) as tYear,
SUM(a.credit) as credit, SUM(a.debit)
FROM telco_transactions AS a
WHERE a.telco_id = '1' and DATE(a.created_at) BETWEEN DATE(NOW())-INTERVAL 3 MONTH AND DATE(NOW())
GROUP BY MONTHNAME(a.created_at), YEAR(a.created_at);

Getting multiple maxes of summed values

Consider this sample data:
+----------+------+--------+-----------------+
| username | qnum | qvalue | date |
+----------+------+--------+-----------------+
| Linda | 1 | 2 | 11/14/2017 7:25 |
+----------+------+--------+-----------------+
| Fred | 1 | 1 | 11/23/2017 7:59 |
+----------+------+--------+-----------------+
| Brian | 5 | 2 | 11/17/2017 7:25 |
+----------+------+--------+-----------------+
| Sandra | 6 | 1 | 11/25/2017 7:26 |
+----------+------+--------+-----------------+
| Tom | 6 | 1 | 11/22/2017 7:32 |
+----------+------+--------+-----------------+
| Paul | 6 | 1 | 11/22/2017 7:36 |
+----------+------+--------+-----------------+
| Andrew | 7 | 2 | 11/23/2017 7:37 |
+----------+------+--------+-----------------+
| Luke | 3 | 1 | 11/23/2017 8:03 |
+----------+------+--------+-----------------+
| William | 8 | 1 | 11/23/2017 8:03 |
+----------+------+--------+-----------------+
| Linda | 9 | 2 | 11/15/2017 8:03 |
+----------+------+--------+-----------------+
| Brian | 3 | 2 | 11/17/2017 8:04 |
+----------+------+--------+-----------------+
| Joan | 9 | 1 | 11/23/2017 8:04 |
+----------+------+--------+-----------------+
| Chris | 8 | 1 | 11/23/2017 8:04 |
+----------+------+--------+-----------------+
| Kim | 8 | 1 | 11/15/2017 8:04 |
+----------+------+--------+-----------------+
I am attempting to get the person who has the highest sum of qvalue for last week. I am able to get this information with the following SQL but my problem is that if more than one user has the top score then it does not show both of their names because I am using the LIMIT function. Is there a way to use max and sum together to get the desired result? The desired result would be a result set with both Linda and Brian listed because last week they both had a sum score of 4 and were tied.
SELECT username, SUM(qvalue) AS score FROM trivia_scoreboard
WHERE `date` >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE())+6 DAY AND `date` < CURDATE() - INTERVAL DAYOFWEEK(CURDATE())-1 DAY
GROUP BY username
ORDER BY score DESC
LIMIT 1
You have to join that query with a query that gets everyone's total.
SELECT t1.*
FROM (
SELECT username, SUM(qvalue) AS score FROM trivia_scoreboard
WHERE `date` >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE())+6 DAY AND `date` < CURDATE() - INTERVAL DAYOFWEEK(CURDATE())-1 DAY
GROUP BY username
) AS t1
JOIN (
SELECT SUM(qvalue) AS score FROM trivia_scoreboard
WHERE `date` >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE())+6 DAY AND `date` < CURDATE() - INTERVAL DAYOFWEEK(CURDATE())-1 DAY
GROUP BY username
ORDER BY score DESC
LIMIT 1
) AS t2 ON t1.score = t2.score
DEMO
You can also phrase this using having:
SELECT ts.username, SUM(ts.qvalue) AS score
FROM trivia_scoreboard fs
WHERE ts.`date` >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE())+6 DAY AND
ts.`date` < CURDATE() - INTERVAL DAYOFWEEK(CURDATE())-1 DAY
GROUP BY username
HAVING score = (SELECT SUM(ts2.qvalue) as score
FROM trivia_scoreboard ts2
WHERE ts2.`date` >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE())+6 DAY AND
ts2.`date` < CURDATE() - INTERVAL DAYOFWEEK(CURDATE())-1 DAY
GROUP BY username
ORDER BY score DESC
LIMIT 1
);
The difference between this and the version using join is really a matter of taste. This might have slightly better performance, because of details about how aggregations scale on larger amounts of data.

how to retrieve date from db without seconds

+---------+---------------------+
| user_id | registration_date |
+---------+---------------------+
| 6988 | 2017-07-24 12:10:29 |
| 6985 | 2017-07-23 12:10:00 |
| 6980 | 2017-07-22 11:10:40 |
| 6979 | 2017-07-21 02:30:00 |
| 6978 | 2017-07-20 08:10:15 |
| 6977 | 2017-07-19 12:10:29 |
| 6976 | 2017-07-18 12:10:00 |
| 6975 | 2017-07-17 05:10:02 |
| 6974 | 2017-07-16 06:10:11 |
| 6951 | 2017-07-15 09:10:50 |
+---------+---------------------+
select registration_date from users WHERE registration_date BETWEEN '2017-07-24 12:10' - INTERVAL 10 DAY AND '2017-07-24 12:10';
I am having this data in my sql table and i am trying to get the data between 2017-07-24 12:10 and INTERVAL 10 DAY AND '2017-07-24 12:10'(excluding seconds).
Now i want to get this | 6988 | 2017-07-24 12:10:29 | ...Means i want to ignore the seconds value from the data that is stored in the db and then get the data.so that the desired data with user_id 6988 will come.
select registration_date from users WHERE registration_date BETWEEN '2017-07-24 12:10' - INTERVAL 10 DAY AND '2017-07-24 12:10';
I am trying this...But not working .
Add the min and max value for seconds. In start add the 00 and for the range end 59 as seconds
select registration_date from users
WHERE registration_date BETWEEN '2017-07-24 12:10:00' - INTERVAL 10 DAY
AND '2017-07-24 12:10:59';
For MySQL, you can use DATE and STR_TO_DATE functions to extract/compare dates, e.g.:
SELECT DATE_FORMAT(registration_date, '%Y-%m-%d %H:%i')
FROM users
WHERE registration_date BETWEEN DATE_ADD(STR_TO_DATE('2017-07-24 12:10', '%Y-%m-%d %H:%i') - INTERVAL 10 DAY)
AND STR_TO_DATE('2017-07-24 12:10', '%Y-%m-%d %H:%i');
Here's the documentation.
You can use DATE_FORMAT to get the parts of the date that you want, and compare this.
Since you want a range of dates, you need to test that separately from the time.
WHERE DATE(registration_date) BETWEEN '2017-07-14' AND '2017-07-24'
AND DATE_FORMAT(registration_date, '%H:%i') = '12:10'

MYSQL select sum for existing dates and 0 for future dates

I have been able to select all of the months with values from this year and last if they exist. What I am trying to do is create a future date if nothing exists for it yet with a TotalAmount of 0. I could possibly fill this in using PHP however I am hoping MYSQL will have a simpler solution.
SELECT
DATE_FORMAT(STR_TO_DATE(Invoice.Date, '%m/%e/%Y'), '%m-%Y') AS Date_Month,
SUM(Invoice.Amount) AS TotalAmount
FROM Invoice
WHERE STR_TO_DATE(Invoice.Date, '%m/%e/%Y') BETWEEN DATE_SUB(DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFYEAR(CURDATE()) DAY), INTERVAL 1 YEAR), INTERVAL 2 YEAR) AND NOW()
GROUP BY Date_Month
ORDER BY Date_Month
Current Output:
01-2016 | 103077
01-2017 | 104925
02-2016 | 187065
02-2017 | 32865
03-2016 | 135525
04-2016 | 106500
05-2016 | 98812
06-2016 | 111690
07-2016 | 96193
08-2016 | 123970
09-2016 | 126356
10-2016 | 147454
11-2016 | 160254
12-2016 | 98430
Expected Output:
01-2016 | 103077
01-2017 | 104925
02-2016 | 187065
02-2017 | 32865
03-2016 | 135525
03-2017 | 0
04-2016 | 106500
04-2017 | 0
05-2016 | 98812
05-2017 | 0
06-2016 | 111690
06-2017 | 0
07-2016 | 96193
07-2017 | 0
08-2016 | 123970
08-2017 | 0
09-2016 | 126356
09-2017 | 0
10-2016 | 147454
10-2017 | 0
11-2016 | 160254
11-2017 | 0
12-2016 | 98430
12-2017 | 0
You can do it with a query like this, but is not tested
SELECT
DATE_FORMAT(STR_TO_DATE(Invoice.Date, '%m/%e/%Y'), '%m-%Y') AS Date_Month,
SUM(IF(STR_TO_DATE(Invoice.Date > NOW(), 0, Invoice.Amount)) AS TotalAmount
FROM Invoice
WHERE STR_TO_DATE(Invoice.Date, '%m/%e/%Y') BETWEEN DATE_SUB(DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAYOFYEAR(CURDATE()) DAY), INTERVAL 1 YEAR), INTERVAL 2 YEAR) AND NOW()
GROUP BY Date_Month
ORDER BY Date_Month;