Help ordering a result by date in SQLite - sql

Is there any way in SQLite to ORDER BY a date, and have result be ordered by time rather than alphabetically?
For example:
SELECT * FROM details GROUP BY date;
John | Smith | April 01, 2011
John | Smith | April 03, 2011
John | Smith | April 04, 2011
John | Smith | March 25, 2011
March should come before April.
I'm guessing that the answer here is to store my dates as long timestamps, however I wasn't sure if it could be done more easily with SQLite.
Thanks!

There isn't a built-in DATE type in SQLite (as exists in some other database management systems), but it does have a nice complement of date and time functions: http://www.sqlite.org/lang_datefunc.html
You can use date("April 01, 2011") to get back an ISO-8601 date (e.g., 2011-04-01).
This format has the advantages of both being a readable string and being sortable. 2011-03-25 naturally comes before 2011-04-01 by standard string comparison rules, so there's no special operation required.
So, store your dates in that format, and get that format using the date() function (or other relevant function).

you can convert date to an actual date in order to compare it.
try to add order by julianday(date) to the end of the query
http://www.sqlite.org/cvstrac/wiki?p=DateAndTimeFunctions

date must be a string and not an actual date. You would need to convert date to an actual date. Here is a link to Sqlite date and time functions.
http://www.sqlite.org/lang_datefunc.html

You can do something like this
select * from sometable order by date(thestringDateColumn)
Hope this helps

Related

How to get all months between two dates in sql with data

Please suggest a method where in we could retrieve name of all months in between two dates.
The months may or may not contain data, but as the need is to display monthly trend, we are required to fetch all months in between two date ranges with or without data.
The Output will be like:
Jan | Feb | Mar
----------------------
Data | Data| Data
If you use SQL Server, you can use the MONTH() or DATEPART() function to extract the month from a date. For example, the following statement returns the current month in SQL Server: SELECT MONTH(CURRENT_TIMESTAMP); SELECT DATEPART(month, CURRENT_TIMESTAMP);
You could then do a GROUP BY to determine how many events occur per month
In general "dynamic columns" are much harder to achieve than "dynamic rows" so output that looks like the first of the tables below will be easier to achieve than output that looks like the second.
Easier
Month | Data
-------------
Jan | Data
Feb | Data
Mar | Data
Harder
Jan | Feb | Mar
----------------------
Data | Data | Data
In general, the best approach is to have your SQL queries return data in the first type of structure and then if required transform this to the second type in your "presentation layer", which might be in Excel, PowerBI, SSRS, or on a website, for example.
If you have months where there might be no data to be returned, you need some means of generating the months and then outer joining this to the data. Obviously in general, at least behind the scenes you'll want to be including years in your data in addition months as otherwise all the data from Jan 2020 will be grouped together with that from Jan 2021, which is probably not what you want.
Here is a SQL-Server-friendly snippet which will output all the months (and years) between two dates. At the time of writing, you haven't specified a DBMS, so if you aren't on SQL Server, this may not work for you.
DECLARE #datefrom DATE = '2020-06-01'
DECLARE #dateto DATE = '2021-03-01';
WITH cte AS
(
SELECT #datefrom as MyDate
UNION ALL
SELECT DATEADD(month,1,MyDate)
FROM cte
WHERE DATEADD(month,1,MyDate)<=#dateto
)
SELECT
YEAR(cte.MyDate) CalendarYear,
MONTH(cte.MyDate) CalendarMonth,
DATENAME(month, cte.MyDate) as MonthNameFull,
CONVERT(char(3),cte.MyDate,0) as MonthName3Char
FROM
cte
ORDER BY
Year(cte.MyDate),
Month(cte.MyDate)
The final SELECT query could be OUTER JOINed to your actual data to give you your desired results. Pivoting should then be done in the presentation layer.
An alternative to the cte would be to use a "numbers table" and use that to add a number of months to the start date and limit the output to where the result of adding that number of months is between the two provided dates.

Excel 5 digit Datetime converted in SQL is 2 days ahead

I have a spreadsheet with Datetimes as follows:
I am importing this file into an application so in Javascript I see the date being brought through as the normal 5 digit datetime code:
So far as I expect... However, when I then try getting this datetime readable in SQL Server, I run the following scripts:
select
CONVERT(varchar(25),cast(28540 as datetime),121),
dateadd(D,28540,0)
And the dates all return PLUS 2 days!
The same happens for all dates I pass through. I could easily just remove 2 from the 5 digit number but I don't want to just do that if there is a rule or reason for this?
Any advice on this is greatly appreciated!
Excel dates are tricky. What they do is count the number of days since Dec 30th, 1899 (and early years are not entirely accurate).
One option is:
dateadd(d, 28540, '1899-12-30')
Demo on DB Fiddle:
select dateadd(d, 28540, '1899-12-30') new_dt
| new_dt |
| :---------------------- |
| 1978-02-19 00:00:00.000 |

Earliest and Lastdate for each year in sql

I have a column with 3 columns. I have multiple records for a year. As you see some of my records as follows
ID stardate enddate
1 1/1/2010 5/3/2010
2 2/4/2010 NULL -**EDIT**
3 1/2/2011 5/6/2011
4 3/4/2011 NULL -**EDIT**
I want to get a result for the earliest date in that year and the last date in that year. So output could be like
**EDITED:** 1/1/2010 12/31/2010 - For Year 2010
**EDITED:** 1/2/2011 12/31/2011 - For Year 2011
How can i get that in a query?If you need more info,please ask. Thanks
EDIT: If for the year if one of the columns read NULL then I have to consider the last day of the year as the enddate. i.e.12/31/YYYY. And I need to do that for each year again.
Assuming you use DATE (or related) columns in a MySQL table, something like this should serve your request:
SELECT MIN(startdate),
MAX(enddate),
YEAR(startdate)
FROM my_table
GROUP BY YEAR(startdate);
This groups all entries by year (of the startdate) and show you the minimum and maximum entries for each year as you want. See also the documentation for the DATE function in MySQL.
There are similar date functions and possibilities if you are using an other database system. Usually you can easily find them by googling the database system and something like "date functions".
select MIN(stardate),max(enddate)
from [Tablename]
where YEAR(enddate)=2013

Oracle select dates based on year returning inconsistent results

I'm getting a peculiar problem with an Oracle view I've modified. The idea is I have a base table that stores all election candidates and also has an election date column, telling us what election this candidate was part of, like so.
NAME | ELECTION_DATE
---------------------------
John Smith | 01-APR-2011
Alan Cooper| 02-MAY-2013
The ELECTION_DATE column is stored as a date. We constructed 2 views for 2011 and 2013, using the following statment for 2011.
where election_date >= to_date(2011,'yyyy') and election_date < to_date(2012,'yyyy')
Which we thought would pick up just the John Smith record above, but it didn't. The peculiar thing was that when we did this for the 2013 view.
where election_date >= to_date(2013,'YYYY') and election_date < to_date(2014,'YYYY')
It DID get just the Alan Cooper record. Even more peculiar is that if we did this for the 2011 view.
where election_date >= to_date(2010,'yyyy') and election_date < to_date(2011,'yyyy')
We got just the John Smith record and not the Alan Cooper record, which is what we wanted but not what we expected.
We then changed them both to between statements and they behaved exactly the same i.e. between 2010 and 2011 got the John Smith record, between 2011 and 2012 got nothing and between 2013 and 2014 got the Alan Cooper record.
Whilst I was writing this my colleague managed to fix it by using this more explicit statement.
where election_date between '01-JAN-2011' AND '01-JAN-2012'
But I still want to know why the above statements still worked so strangely? Something I am missing about using to_date functions for just years maybe?
Did you look at what your to_date() functions actually produced?
select to_date(2011, 'yyyy'), to_date(2012, 'yyyy'), to_date(2013, 'yyyy')
from dual;
TO_DATE(2011,'Y TO_DATE(2012,'Y TO_DATE(2013,'Y
--------------- --------------- ---------------
01-MAY-11 01-MAY-12 01-MAY-13
Based on those dates the results you got are correct.
If you don't specify the month and day then they default to the first day of the current month, although the time defaults to midnight. From the documentation for date time literals, which is the only official reference I can find for this behaviour:
If you specify a date value without a time component, then the default
time is midnight (00:00:00 or 12:00:00 for 24-hour and 12-hour clock
time, respectively). If you specify a date value without a date, then
the default date is the first day of the current month.
If you're going to use
where election_date between '01-JAN-2011' AND '01-JAN-2012'
... then you should still use to_date() as you're relying on a default date format mask that might change in the future, and is session dependent. between is also inclusive, so using that your 2011 view would include an election held on 01-Jan-2012, which probably isn't what you want, so using >= and < is maybe safe. Alternatively use date literals:
where election_date >= date '2011-01-01' and election_date < date '2012-01-01'
Try extracting the year as a VARCHAR2 and doing the comparison
select * from table where to_char(ELECTION_DATE, 'yyyy') = `2011`
or to_char(ELECTION_DATE, 'yyyy') = '2012'

Storing a time difference in SQL

In my application, I have a database storing a calendar of events:
id | name | date
----+--------------------+--------------------
1 | Birthday Party | 2013-04-27 16:30:00
2 | Dinner Reservation | 2013-03-20 17:00:00
3 | Sunday Brunch | 2013-03-31 11:15:00
When viewing events in the application, users should be able to configure how far in advance from the present moment they wish to view events, stored as a value in the database:
username | datediff
----------+------------------------------------------
user123 | 2 days in advance
goodguy | 93 days in advance
spudly | 365 days in advance
aaaaaa | 17 days, 3 hours, 30 seconds in advance
My question is: what is the best (i.e., most SQL-idiomatic) way to store such a date differential? I could store the time difference as a number in milliseconds, but is there some built-in SQL datatype that is suitable for date differentials, rather than just particular points in time? Is something like DATETIME or TIMESTAMP appropriate for this task?
It must be a relative difference -- for example, for "2 days in advance" I'm not interested in storing a particular date two days in the future, because I'd like the user to see events for the next two days every time he looks at the application.
I'm using Microsoft SQL Server 2008, if it makes any difference.
(This may be a duplicate, but all my search attempts have turned up results about datediff -- which is used to calculate time differences -- but nothing about how best to store time differences.)
Standard SQL has a specific data type for date and time durations: interval. SQL Server doesn't support the interval data type.
DateDiff() returns a signed integer. If you need to store the SQL Server equivalent to a SQL interval, you'll need to store an integer. The integer is a count of the number of datepart boundaries, so you also need to store what kind of datepart boundary the integer refers to. Without the datepart, the signed integer 3 could just as easily mean 3 years or 3 seconds.
As a practical matter, I think I'd rather calculate a timestamp for the reminder, and store that instead of the integer and datepart that define an interval. A timestamp can be indexed and queried much more simply than the integer and datepart. And without the need to support recurring events, I don't see a compelling reason to build a solution more complicated than that.