I have a page that displays all projects ordered by dates. When you click on a project you are brought to a page project-single.php?id=123 where I have a previous and next button. All of the projects have an id (which is in no sequential order aka not auto_incremented), and a date of creation timestamp (in the form of 2012-07-20 00:36:20) in the projects table in the database. I am trying to think of an efficient way to get the id of the project both before and after the id=123 in terms of date for the prev next buttons. But I cannot think of an easier way than creating an array with the id and date_created and comparing dates; which as you can imagine would get quite taxing on the server as this is a page accessed often. Does anyone have a cleaner solution?
You might consider changing your timestamp to a Unix timestamp instead of a string. Unix timestamps are simple integers, which are easy and efficient for a database to compare.
With a comparison operator, an index on the timestamp, and a LIMIT 1, you should have a very fast SQL statement. Here's some example code:
-- For getting the next project.
SELECT * FROM projects WHERE date_created > :current_project_date ORDER BY date_created ASC LIMIT 1;
-- For getting the previous project.
SELECT * FROM projects WHERE date_created < :current_project_date ORDER BY date_created DESC LIMIT 1;
I'm not familiar with MySQL, so these results may need some tweaking, but that's the gist.
Related
I have a PHP application that records the sessions of various devices connected to a server. The database has a table session, with the columns device_id, start_date, end_date. To know the number of devices connected on a given date, I can use the request :
SELECT COUNT(DISTINCT device_id)
FROM session
WHERE :date >= start_date AND (:date <= end_date OR end_date IS NULL)
where :date is passed as a parameter to the prepared statement.
This works fine, but if I want to know the number of devices for every days of the year, that makes 365 queries to run, and I'm afraid things could get very slow. It doesn't feel right to be iterating on the date in PHP, it seems to me that there should be a more optimal way to do this, with a single query to the database.
Is it possible do this with a single query?
Would it actually be faster than to iterate on the date in PHP an running multiple queries?
EDIT to answer the comments :
I do want the number for each separate day (to draw a graph for example), not just the sum
the datatype is DATE
If I understand correctly then you first need a table of dates, something like:
create table dates(dt date);
insert into dates(dt) values
('2001-01-01'),
('2001-01-02'),
...
('2100-12-31')
And use a query like so:
select dates.dt, count(session.device_id)
from dates
join session on start_date <= dates.dt and (dates.dt <= end_date or end_date is null)
-- change to left join to include zero counts
where dates.dt >= :date1 and dates.dt <= :date2
group by dates.dt
PS: since you mentioned charts I might add that it is possible to avoid the table of dates. However, the result will only contain dates on which the count of devices changed. Chart APIs usually accept this kind of data but still create data points for all dates in between.
I am working on a school project where I have to make a todo web app. now i have a little problem. I need to get the records that are running out of time (think 20% of the whole task left). now i'm looking for a solution in php or a sql statement with which i can retrieve only those records.
I tried many statements but i cant get one to work.
SELECT * FROM tasks
WHERE user_id='$user_id'
AND '$currentDate' BETWEEN start_date AND end_date
The above one is working with the date but not with time.
So now I need to have a statement or function that only retrieves the tasks that are almost finished. I've added a screenshot of the database and the application to clarify it a bit.
i hope someone could help me. (this is my first time using stackoverflow so sorry if i do something wrong)
First, you should not be munging your query with constants, date or otherwise. So, use now().
Second, combine the date/time into a single column
Third, you seem to want and:
WHERE user_id = ? AND
NOW() >= start_datetime AND
NOW() < end_datetime
If you want to store the date/time in separate columns, then you can combine them:
WHERE user_id = ? AND
NOW() >= ADDTIME(CAST(start_date as DATETIME), start_time) AND
NOW() < ADDTIME(CAST(end_date as DATETIME), end_time)
Basically I have a website where user vote on projects posted by users or "Support" everytime a user clicks the support button, it goes into a table and stores 3 things, a normal auto increment identifier, the user_id that 'supported' it and the project id they supported. Now everyday we want to display 'Top projects' on the homepage. This will my guess be done with a php script and a cron job. I can't really think of how to query the database properly to determine X amount of top projects. (Most likely 5 or 10) Iv'e thought about this for a while, but I can't think of an answer. Any ideas/answers help alot! Thanks.
Well, your going to have to add a time stamp of one sort or another to that database. So you can query by the day from midnight to 11:59p. I'd say datetime format ie: YYYY-MM-DD HH:MM:SS (its in 24 hour format)
From that if handled correctly you could do something like
<?php
$todayMidnight = date('Y-m-d'). ' 00:00:00';
$todayLastMin = date('Y-m-d'). ' 23:59:59';
$result = mysql_query("select * from the_table where the_Time BETWEEN $todayMidnight AND $todayLastMin LIMIT 10 order by the_count");
?>
Suppose, you have an SQL database table called votesTable with a field numberOfVotes.
Without a cron-job or such, you might run this MySQL-query
SELECT *
FROM votesTable
ORDER BY votesTable.numberOfVotes DESC
LIMIT 10
to retrieve the to top 10 vote entries.
This YouTube video PHP Tutorial: Simple Rating / Voting System [part 01] may help (tutorial author's page).
I have a php page which allows a user to sort pieces of information by several factors. A new requirement is to sort by "all items which have been registered in the last 15 days". I store my dates in the MYSQL table as mm/dd/yyyy.
The information is passed and picked up on the same page using the $_GET variable but I am unable for some reason to get the code to work. I have looked on numerous website but am unable to find a solution that works.
Ultimately, the script would work as follows:
select all persons who's KDATE is within 15 days of today's date (e.g., if today is 8/19/2010, everybody who registred from 8/04/2010 and on would appear).
My script so far (which does not work) is:
if (isset($_GET['date'])) {
$query = "SELECT *
FROM persons
WHERE DATE_SUB(CURDATE(),INTERVAL 15 DAY) <= KDATE
ORDER BY KDATE ASC";
}
Update 1:
KDATE IS TEXT - i apologize but the KDATE is stored as TEXT
Update 2:
The answer provided by Colin solved my issue. I will look into trying to convert the data into datetime format but am hoping the group can provide realistic benefits of doing so.
Thank you all again
First of all, it's a really bad idea to use VARCHAR instead of DATE if you want a collumn with dates only.
If you want to use a string as a date, you'll need to convert it with STR_TO_DATE() and you might wan't to use those instructions to correctly format your date.
This should do it:
SELECT *
FROM persons
WHERE DATE_SUB(CURDATE(),INTERVAL 15 DAY) <= STR_TO_DATE(KDATE, "%c/%d/%Y")
ORDER BY STR_TO_DATE(KDATE, "%c/%d/%Y") ASC
Because kdate is VARCHAR, you need to use STR_TO_DATE to change it to a DATETIME.
You need to fix kdate data that does not fit that pattern (mm/dd/yyyy) before running this:
SELECT *
FROM persons
WHERE DATE_SUB(CURDATE(),INTERVAL 15 DAY) <= STR_TO_DATE(KDATE, 'm/%d/%Y')
ORDER BY STR_TO_DATE(KDATE, 'm/%d/%Y') ASC
This means that an index on kdate is useless, because of having to change the data type.
Once it's a DATETIME, you can use DATE_FORMAT to change the format as you like.
I have a list of dates in a table in a MySQL database (the dates when a charity bookstall is to be held), which I want to display on a page. On one page I'm displaying the date of the next stall, and on another the dates of the stall in the next month. (Currently I'm using an unordered HTML list and selecting the dates with PHP, but it's a bit messy, and I also want to tie in the dates with the fundraising totals that are stored in the database).
I want to put the dates in a database though so that I can tie in the dates with the fundraising totals for each week. I'm thinking that once I can identify the date with the nearest up-coming date that I can use 'LIMIT 1' to select the next week's date for display, and 'LIMIT 4' say for where I need to display the dates for the next month, but what I can't figure out is how to identify the record with the nearest up-coming date - identifying the current date and then selecting the nearest date...I have a feeling there's probably one of the MySQL date functions that can be persuaded to help out in this, but can't figure out exactly how.
Any ideas on how I can do this?
If I understand correctly, you can just pick up next four dates that are after today.
In MySQL you could use the CURDATE() function for the 'today' bit, then apply an order and limit to your select statement. For example,
SELECT stall_date
FROM stall_dates
WHERE stall_date >= CURDATE() -- >= assumes you want today's to show too
ORDER BY
stall_date
LIMIT 4
Use ORDER BY stall_date DESC to reverse the ordering if needed.
If your column is a DATETIME field, you can identify the next by using SELECT...WHERE event_date > "2009-11-06" and ORDER BY event_date.
SELECT * FROM so_events
WHERE event_date > "2009-11-06 15:36:00"
ORDER BY event_date ASC
LIMIT 4
MySQL will internally do the work for you and select rows where whose timestamp is greater than the one you specify in the WHERE clause.