Sort by Time using SQL - mysql

I am using VB and MySQL. I have a field named xTime and the data type is TIME. I am trying to find a way to order it ASC or enable it to have the PM/AM in it. Right now my Data is as follows and I need the 3:20 and 5:50 to be after since those should be pm. Any ideas?
62 4 3 03:20:00
61 4 3 05:50:00
56 1 1 07:40:00
Here is my SQL Statement:
SELECT ReserveID, MembershipID, Player_Count, `Time`, CourseID, `Date`
FROM reserve
WHERE (CourseID = 1) AND (`Date` = CURDATE())
ORDER BY `Time`

Actually, your code and your data seem to be fine. Your code is ordering by time ascendingly and your results are displaying it the way they should. The issue is that you're interpreting the data in the wrong way:
I need the 3:20 and 5:50 to be after since those should be pm
3:20 and 5:50 must be before 7:40 always, because those are all AM times. 3:20 PM is equal to 15:20 and 5:50 PM is equal to 17:40.

Related

How can I filter rows according to a date range when only year, month and day are available?

I have data such as these:
id year month day
1 2020 11 1
2 2020 11 1
3 2020 12 31
4 2020 12 31
5 2021 1 1
6 2021 1 1
7 2021 1 31
8 2021 1 31
9 2021 2 1
10 2021 2 12
I wish to SELECT all rows between 2 dates.
I realise that I could convert the year/month/day to a timestamp which would make this very easy. Actually the timestamp is already there, however, the underlying table is huge (tens of billions of rows) and the DB administrator has set up indexing/clustering on the year/month/day columns in order provide performant queries. Queries that directly use the actual timestamp in a WHERE clause take far too long to run (hours) whereas queries that use year/month/day run within seconds.
Here is a db<>fiddle
Just to clarify, this is a way to do it, but your problem is your DBA, your arquitechture, etc. etc. You won't solve this by this way, neither the time or resources wasted. Maybe you need to ask a proper way to do this with non SQL database in DBA stack exchange site.
Anyway, for the to-know way:
Convert data to datestamp ISO: yyyyMMdd with CONCAT and LPAD
Compare the data as normal integer
Example: (of course you can change the values of your search)
SELECT * from dt WHERE CONCAT(year,LPAD(month, 2, '0'),LPAD(day, 2, '0')) BETWEEN 20201231 AND 20210101

Selecting between dates in mysql

Need to track and bill delivers based on date, for example if a deliver came in After 01/18/2010 but before 02/11/2010 it would be billed to Job no. 198.
I pretty much know it would be:
SELECT `no` FROM `jobs` WHERE 'start_date' >'2010-01-18' AND <`2010-02-11`;
in order to get '2010-01-18' AND < '2010-02-11', I have to look in the data base of course that defeats the purpose
I am given the Var=$delivery_date
And I am stuck right here.
How can I get the between dates without looking each time.
Sample of data base
no Start Date
198 2010 01 18 14:35
199 2010 02 11 12:10
200 2010 03 07 12:33
201 2010 03 31 17:35
202 2010 05 25 05:05
203 2010 06 20 01:05
204 2010 07 14 08:50
205 2010 07 21 11:31
206 2010 09 07 03:47
I hope I explained it well enough. I look at the manual and other questions but it always seems like they only have one date that is a variable and all of mine are
PS changing the format or method of the tables is not an option unless you can point me towards the time travel section
You can use the following select statement:
SELECT * FROM jobs WHERE date(start_date) BETWEEN "2010-02-08" AND "2010-03-15";
so you only take the date portion into account, not the time.
so with your date format it would be something like
SELECT * FROM jobs WHERE date(STR_TO_DATE(start_date, '%Y %m %d %h:%i')) BETWEEN "2010-02-08" AND "2010-03-15"
Looks like you want to find a jobs record with the largest start_date that's also less than $delivery_date. Here's the query
SELECT no
FROM jobs
WHERE `start_date` < $delivery_date
ORDER BY `start_date` DESC LIMIT 1
If $delivery_date is set to 2010-02-08, the above query will return 198 like you expected.
If $delivery_date is set to 2010-03-15, the above query will return 200.
thanks to ekad this worked perfectly
SELECT no
FROM jobs
WHERE start_date < $delivery_date
ORDER BY start_date DESC LIMIT 1
after the query the job no i need is first one

MySQL: Group by Austral year?

Let's say we have a simple table like so
DATE VALUE
--------------------
2013-01-01 23
2013-06-12 34
2013-07-22 788
2013-12-16 234
2014-01-23 56
2014-04-19 88
2014-09-23 7987
2014-11-05 66
2015-02-17 987
2015-05-05 896
Now let's suppose we want to extract the mean values grouped by year, we would use
SELECT AVG(`VALUE`) FROM tablename GROUP BY YEAR(`DATE`)
However, what if we define the year not from January to December, but rather from July to June (which makes quite a bit of sense for a lot of data if you're living in the Southern hemisphere).
I am sure there must be an easy way to achieve a July YEAR to June YEAR+1 grouping. It just seems to elude me.
-- EDIT --
Awesome! Two good solutions arrived within minutes of posting this question, that both deserved to be accepted. I accepted Roland's solution because of its brevity, but Leo Tara's reply made me aware that I forgot about outputting the associated austral year. So based on both answers I came up with this solution which does exactly what I was asking for:
SELECT
YEAR(`DATE` - INTERVAL 6 MONTH) as `australyear`,
AVG(`VALUE`)
FROM tablename
GROUP BY YEAR(`DATE` - INTERVAL 6 MONTH)
Just add 6 month to the date when grouping. I don't know the exact syntax in case of mysql, sorry.
Pseudocode:
SELECT AVG(`VALUE`) FROM tablename GROUP BY YEAR(`DATE` + '6 MONTHS');
Try this:
SELECT AVG(`VALUE`)
FROM tablename
GROUP BY
CASE
WHEN MONTH('DATE') BETWEEN 1 AND 6 THEN YEAR('DATE') - 1
ELSE YEAR(`DATE`)
END
If you want to show year on field list you must rewrite your query in this way:
SELECT
CASE
WHEN MONTH('DATE') BETWEEN 1 AND 6 THEN YEAR('DATE') - 1
ELSE YEAR(`DATE`)
END, AVG(`VALUE`)
FROM tablename
GROUP BY
CASE
WHEN MONTH('DATE') BETWEEN 1 AND 6 THEN YEAR('DATE') - 1
ELSE YEAR(`DATE`)
END
Test on Sql Fiddle

Mysql SQL for "replace everything but this" where xxx

I've got a terrible database on a project and they've used a text field for dates.
So, I need to build a view that has only the year in one column. The problem is that I have dates with any standard format like:
01-01-2012
01.01.2012
01 01 2012
1/1/2012
01/2012
1/2012
2012
01.2012
Is there any way to build an SQL (MySQL) to get only those 4 year digits to build a view?
Thanks a lot for your help!
It really depends on the whole data structure, you can use REGEX or String functions.
For example, with your sample data the last 4 digits on the right are the year so using
SELECT RIGHT(fieldname, 4) FROM table
would work. If that pattern doesn't work then you've either got to use concat and start splitting them or write a REGEX statement.
If RIGHT will work then you can do an INSERT SELECT
INSERT INTO table (yearcolumn)
SELECT RIGHT(fieldname, 4) FROM table
You can use REGEXP matching, to get rows from given year. There's no way to get a capture from regular expression though.
However, if the year part is alwayst last 4 digits, use RIGHT(). Otherwise, you will need to do reformatting client-side.
This may also help. This is Oracle query for the whole current year. It can be easily converted to any SQL. It uses recursive query to build annual table. Replace SYSDATE and Oracle formats with your version of SQL formats and system date:
WITH data(r, start_date) AS
(
SELECT 1 r, TRUNC(SYSDATE, 'YEAR') start_date FROM dual -- start_date: 1/1/2013
UNION ALL
SELECT r+1, TRUNC(SYSDATE, 'YEAR')+r-1 FROM data WHERE r < 365 -- any number: end_date - start_date or get the number of days in your year your way...
)
SELECT start_date
, TO_CHAR(start_date, 'YYYY') curr_year
, TRUNC(start_date, 'IW') wk_starts
, TRUNC(start_date, 'IW') + 7 - 1/86400 wk_ends
, TO_NUMBER (TO_CHAR (start_date, 'IW')) ISO_wk#
FROM data
/
START_DATE CURR_YEAR WK_STARTS WK_ENDS ISO_WK#
-----------------------------------------------------------------------
1/1/2013 2013 12/31/2012 1/6/2013 11:59:59 PM 1
1/1/2013 2013 12/31/2012 1/6/2013 11:59:59 PM 1
...
12/28/2013 2013 12/23/2013 12/29/2013 11:59:59 PM 52
12/29/2013 2013 12/23/2013 12/29/2013 11:59:59 PM 52
12/30/2013 2013 12/30/2013 1/5/2014 11:59:59 PM 1

How can I exclude upper limit in BETWEEN sql server

I am using SQL Server as my database. I am searching for a row for the date that I have entered. This means searching rows where submission_date is exactly '12/13/2011'. First I am converting the search criteria date to milliseconds
i.e.
Dec 13 2011 00:00:00 ='1323727200000'
Dec 14 2011 00:00:00 ='1323813600000'`
SELECT *
FROM log_file
WHERE submission_date BETWEEN '1323727200000' AND '1323813600000'
This query will search for Dec 13 Midnight to Dec 14 Midnight, but I want to skip the upper limit value i.e. from Dec 13 2011 00:00:00 to Dec 13 2011 59:59:59. For this I thought to use >= and <. Is this a right approach?
Having done this, I have a iBatis xml where I am writing the following which is giving me error.
<isNotEmpty prepend="AND" property="submissiondate">
submission_date <![CDATA[ >= ]]> #submissiondate # AND <![CDATA[ < ]]> #submissiondate #
</isNotEmpty>
Please suggest if this is the right approach.
Thanks
Yes, you'd use >= and < typically for time/date range queries
Alternatively, you could subtract 3 milliseconds from the upper limit to get the highest datetime (not newer datetime2) value for that day (xxx 23:59.59.997)
SELECT * FROM log_file
WHERE submission_date BETWEEN 1323714600000 AND 1323801000000-3
Note: subtracting 1 would probably be OK if everything is milliseconds...
Edit, example of why 3ms
SELECT
DATEADD(millisecond, -1, '20111214'), -- 2011-12-14 00:00:00.000
DATEADD(millisecond, -2, '20111214'), -- 2011-12-13 23:59:59.997
DATEADD(millisecond, -3, '20111214') -- 2011-12-13 23:59:59.997
And interestingly, are you sure this is midnight?
For 1323813600 seconds, I get 2011-12-13 22:00:00
On SQL Server:
SELECT DATEADD(second, 1323813600, '19700101')
On MySQL
SELECT FROM_UNIXTIME(1323813600)
In your case, where "date" seems to be of type BIGINT, why not just subtract 1 from the upper interval limit?
SELECT * FROM log_file
WHERE submission_date BETWEEN 1323714600000 AND 1323801000000 - 1
Of course, this wouldn't work with floating point numbers or decimals...
Yes, if you have to skip the upper limit - you should use
WHERE Date >= '20111213' AND Date < '20111214'
Of course - if your column's type is DATETIME