I would like to dynamically search for a date in my database according to my $data input.
Dates are stored as date-times and are usually displayed as ex: "2016-05-11".
With a MySql DB my clause was:
Select * From Table WHERE ( Table.date LIKE '$data%' )
So if the user enters "20" the results will be all dates that start with 20. If the user enters "2016-05" the results will be all dates that start with 2016-05, making my search perfectly working.
When deploying over a Sql Server 2008. I realized 2 things.
1) If i use the LIKE function as Such
Select * From Table WHERE ( Table.date LIKE '%$data$%')
The function will work for a value of "2016" , but would return 0 results when a value of "2016-" is entered.
2) If i use the function DATETIME as such
Select * From Table WHERE ( DATEPART(year, Table.date) LIKE(OR)= '$data')
The function will return correct values when $data = 2016, but will return nil values when the $data = '201' for example, hence making it not dynamic.
What am i doing wrong?
Implicit conversion is just bad, bad, bad -- in SQL or most other programming languages.
LIKE acts on strings. If you want it to work on strings, then explicitly make sure that the parameters are strings. This is true in MySQL and SQL Server.
If you want to use LIKE on the year, then use DATENAME() rather than DATEPART():
WHERE DATENAME(year, Table.date) LIKE '$data'
However, I would encourage you to think about dates using date-based constructs, such as date ranges.
I just realized my stupid mistake.
I needed to add a wildcard to my LIKE clause using DATEPART as such.
Select * From Table WHERE ( DATEPART(year, Table.date) LIKE = '$data%' ) .
Works perfectly.
But i would love other suggestions to simplify splitting $data into YYYY , MM , DD and then testing each element.
I would strive to keep Table.date free of manipulation, so indexes are used.
Instead you can use a CASE expression to convert the search parameter to a date range by adding the missing parts:
Lower bound:
CASE LENGTH($data)
WHEN 8 THEN $data + '01'
WHEN 7 THEN $data + '-01'
WHEN 5 THEN $data + '01-01'
WHEN 4 THEN $data + '-01-01'
ELSE $data
END
Upper bound:
CASE LENGTH($data)
WHEN 8 THEN DATEADD(MONTH,$data + '01',1)
WHEN 7 THEN DATEADD(MONTH,$data + '-01',1)
WHEN 5 THEN DATEADD(YEAR,$data + '01-01')
WHEN 4 THEN DATEADD(YEAR,$data + '-01-01')
ELSE DATEADD(DAY,$data,1)
END
Related
I have a basic SQL knowledge and I am trying to retrieve data from my database based on the date a user chooses. So, if the user selects 2018-03-01 I want to display the data for the date value 2018-03-02.
I can search data for a specified date in the following way:
select * from FLIGHTS where DEPARTURE_DATE = '2018-03-01';
Now I want to search the data for the date next to the specified so for '2018-03-02' in this case. I cant directly search for 2nd March because I don't know what date the user will choose
So is there any way to query data for the date next to the one specified?
I have already tried looking up everywhere but couldn't find anything that makes sense to me.
Thx
I think this works well. By the documentation for date/time functions, you should be able to do something like,
select * from FLIGHTS where DEPARTURE_DATE = '2018-03-01' + INTERVAL 1 DAY
What sort of element are you using for the user to be able to get their date and what is your codebase? We have mysql for the DB but we need to know if your codebase is c#, PHP etc.
Most languages generally have a function to allow you to add days to a datetime, if for instance you used C# and had a datetime selector posting its value you can do:
DateTime dateField = postedDateTime.AddDays(1);
from there you can easily escape the value and push it through your db call.
or PHP:
$dateField = date('Y-m-d', strtotime($postedDateTime. ' + 1 days'));
If you would like a date range (date selected and the next day) then you would adjust your php code to have:
$dateFrom = $postedDateTime;
$dateTo = date('Y-m-d', strtotime($postedDateTime. ' + 2 days'));
$dateTo = date('Y-m-d', strtotime($dateTo. ' - 1 seconds'));
//DB Query
$query = "select * from FLIGHT where DEPARTURE_DATE >= :dateFrom AND DEPARTURE_DATE <= :dateTo";
The above assuming you're using pdo, but you can see how to adjust for your situation. I am also assuming the datetime is based on midnight for each day so you may need to adjust your dateTo to take from 1 second before midnight the day after just so you can get the entire days data
You can make use of interval as day as mentioned in the answer. Along with day you can also have day_minute, day_hour,day_second but be sure when you are adding decimals on these.
I work for a gun club and we are trying to find the total number of targets shot at during a specific year. The table contains totals from years 2000-2018 and I am trying to write a query that will look at the string for the date of the shoot which is in a format like this 2010-06-13 00:00:00.000 I just care about the year so I created this query:
SELECT SUM(ShotAt) AS TotalTargets
FROM MemberShootsC
WHERE GunClubNumber = 210015 AND ShootDate LIKE '2007-%%-%% 00:00:00.000'
If I run the query up to the AND clause it works and returns a total. However, I get a null value if I highlight the whole thing. I have tried variations of the string as well. Such as this '2007%' and this '2007-- %'
Not sure what I am missing. Any help is appreciated.
Don't convert to string to query for a year, use YEAR() function instead:
SELECT SUM(ShotAt) AS TotalTargets
FROM MemberShootsC
WHERE GunClubNumber = 210015 AND YEAR(ShootDate)=2007 -- MySQL
You could also use a range query
SELECT SUM(ShotAt) AS TotalTargets
FROM MemberShootsC
WHERE GunClubNumber = 210015 AND ShootDate BETWEEN '2007-01-01' AND '2007-12-01 23:59:59.999'
Note: The above assumes that you do not store dates as strings. The function to use depends on RDBMS. In MS SQL Server you would use DATEPART(year, ShootDate) = 2007
I am wanting to show current month data. But when I am using this query, then generating extra single string from query.
$queryCurentMonth = $this->Bookings->find('all')
->where(["MONTH(Bookings.created)" => "MONTH(CURRENT_DATE())"]);
Generating :
SELECT
*
FROM
`bookings` `Bookings`
WHERE
MONTH(`Bookings`.`created`) = 'MONTH(CURRENT_DATE())'
This = 'MONTH(CURRENT_DATE())' , it is generating blank data. How we can perfect this query.
MySQL is treating your RHS value as string in
MONTH(`Bookings`.`created`) = 'MONTH(CURRENT_DATE())'
'MONTH(CURRENT_DATE())' shouldn't have single quotes around it. Instead it should be like this
MONTH(`Bookings`.`created`) = MONTH(CURRENT_DATE())
Try to compare year also as function MONTH() returns only a number 1 through 12, the query would return all records for a Month of all years, rather than only the current year. Use both MONTH(), YEAR() to compare months for the current year.
MONTH(`Bookings`.`created`) = MONTH(CURDATE()) AND YEAR(`Bookings`.`created`) = YEAR(CURDATE())
Finally, I have got a solution. it is working finely now.
$queryCurentMonth = $this->Bookings->find('all')
->where(["MONTH(Bookings.created)" => date("m")]);
I have an SQL table with 6 columns like so:
id date time location description unix
My table is used for an event planner web app I'm trying to write.
id is just an incremented identifier
date is just a date in this form: Mon Nov 01 2016
location contains where the event takes place
description is what the event is
I have a unix date stamp for each date - my goal is to output ONLY the rows of the table that have the unix date stamp of the current day.
In pseudocode it would look something like this:
currentdate = currentunixdate()
from table select rows where unix == current
This is what I TRIED but there is something wrong with it...
$current = time();
$data = $con->query('SELECT id, date, location, description, time, unix from calendar WHERE unix LIKE '$current'');
EDIT: Just need to know how to select the particular rows - I have done the rest
date is just a date in this form: Mon Nov 01 2016
this is wrong.
it should be a date field, and hold a value like 2016-11-01. Note that it should be this way. No objections. No excuses.
I have a unix date stamp for each date
That's quite strange because there are nearly 100000 timestamps for each date. You better change this as well. But nevertheless, to convert unix timestamp you have to use date() function
$date = date("Y-m-d", $timestamp);
What we are missing in the question is the structure of you table in terms of MySQL field types.
There are several ways your question can be interpreted, mostly as there is a TIMESTAMP field type which, from your question, you don't seem to be using.
The way I understand your question is that you have a non-time field (e.g. VARCHAR or INT) in which you store the timestamp obtained from the code.
If this is the case, then you really need to look into the MySQL date/time fields as these will provide for everything you need when it comes to dates.
The primary downside of a timestamp as string/number is that it points to a specific second (or millisecond) on the machine it was generated on. It does not contain any timezone information and more importantly it will force your query to search between two values (one for the start of the day and one for the end).
While this doesn't seem too hard:
$time = time(); // this is now
$day = (60 * 60 * 24);
$begin = $time - ($time % $day);
$end = $begin + $day;
$sql = 'SELECT id, date, location, description, time, unix FROM calendar WHERE unix BETWEEN ' . $begin . ' AND ' . $end;
You will have to calculate the range every time you want to use it.
If you would make the unix field to a mysql TIMESTAMP field (which is maybe what your teacher has told you and you already have this, I don't know), it gets very easy.
You still need to convert the timestamp to a date, but that is built in to MySQL (and thus fast).
$time = time(); // this is now
$date = date('Y-m-d', $time);
$sql = 'SELECT id, date, location, description, time, unix FROM calendar WHERE DATE(unix)="' . $date . '"';
and you also get to make that overview for the entire month
$time = time(); // this is now
$year = date('Y', $time);
$month = date('m', $time);
$sql = 'SELECT id, date, location, description, time, unix FROM calendar WHERE YEAR(unix)="' . $year . '" AND MONTH(unix)="' . $month . '"';
Now, some last tips for using a database with PHP (or any language really), make sure to look into prepared statements, as these will help you prevent SQL-injection from day one.
At the very least, if you don't get around to dive into prepared statements (which you should, as it'll make your programming life easier and safer) you can look into sprintf, which will help you prevent quotation issues such as your question code.
Example
$sql = sprintf('SELECT id, date, location, description, time, unix FROM calendar WHERE YEAR(unix)="%s" AND MONTH(unix)="%s"', $year, $month);
sprintf is no substitute for prepared statements, and will not help you prevent SQL-injection.
I'm curious what the right way is to construct a query where the rows are pulled based on a timestamp that represents a specific month. Given that different months have different numbers of days, is there a way to generate a query that always gives you the rows where the timestamp contains the current month so that the results would only include the current month?
Do you mean something like this
SELECT * FROM tbl WHERE
MONTH(timesp) = MONTH(NOW()) AND
YEAR(timesp) = YEAR(NOW());
You can use the FROM_UNIXTIME() function:
SELECT *
FROM tableName
WHERE MONTH(FROM_UNIXTIME(timestampField))==6
Just use MONTH:
select *
from foo
where month_column = MONTH(getdate())
and year_column = YEAR(getdate())
Try this sql.
select *
from yourtable
where yourdatefield>=DATE_SUB(CURDATE(),INTERVAL 1 MONTH);
You're looking for something like this:
SELECT * FROM table where MONTH(date_row) = $month;
If you have an index on your date field, then this is efficient (T-SQL syntax, the idea applieas to any RDBMS though)
SELECT
*
FROM
tableName
WHERE
dateTimeField
BETWEEN
-- build the string 'YYYY-MM-01', cast back as a datetime
CAST(
CAST(YEAR(GETDATE()) AS varchar) + '-' + CAST(MONTH(GETDATE()) AS varchar) + '-01'
AS datetime
)
AND
-- add one month, subtract one day
DATEADD(mm, 1,
-- build the string 'YYYY-MM-01', cast back as a datetime
CAST(
CAST(YEAR(GETDATE()) AS varchar) + '-' + CAST(MONTH(GETDATE()) AS varchar) + '-01'
AS datetime
)
) - 1
Of course any other method to get two datetime values in the right range would work.
SQL Server has LEFT(CONVERT(varchar, GETDATE(), 120), 8) + '01' to convert a datetime to string, other Db servers have their own functions to do the same. Maybe you can calculate the two values in the calling application more easily - how you get them, is not the point.
The point is that BETWEEN can use an index, whereas the other solutions that work with WHERE MONTH(dateTimeField) = 6 will trigger a table scan, which is about the slowest operation you can do on a table.