MySQL Conditional Select Replace Query - php

I have found myself in need of replacing certain returned results from a MySQL Select Query. I have the following table and data (simplified for example purposes)
uid | duration | range | unique | stamp
-----------------------------------------------------------------
23 | d | 43 | 1 | 1
24 | d | 65 | 0 | 2
25 | d | 76 | 0 | 3
26 | d | 33 | 0 | 4
27 | d | 44 | 1 | 5
28 | d | 43 | 1 | 6
29 | d | 67 | 0 | 7
30 | d | 88 | 0 | 8
31 | d | 63 | 0 | 9
The stamp column is what I want to do the replace on. Rather than a simple text replace, I was wondering if its possible to run some sort of user defined function on the column and replace it dynamically.
For example If the data returned in the stamp column is a 1, I would like it to replace it with today's timestamp, if it is a 2 then yesterdays timestamp, a 3, the day before yesterdays and so on and so forth.
So my question is, is it possible to point REPLACE to a function that processes the value and then returns what to replace it with. Or if not, is there another way to accomplish this.
I could obviously post process the returned data in PHP and make the changes, but with millions of records returned, it will increase the load time considerably.
EDIT TO MAKE THINGS A BIT CLEARER: I want to replace the stamp column in the data returned from a SELECT Query, I am not storing the data anywhere, or replacing the data in the table. The table will remain unchanged.
Thanks

Absolutely possible:
UPDATE stamps
SET stamp = CURRENT_DATE - INTERVAL stamp - 1 DAY;
Fiddle here. Note that you have to decrement the stamp value by 1 to "minus 0 days" for a stamp of 1. If you remove the - 1, you'll end up storing yesterday's date for stamp values of 1.
UPDATE to answer your question about doing it on SELECT:
SELECT CURRENT_DATE - INTERVAL stamp - 1 DAY
FROM stamps;
Updated Fiddle here

You can use the case statement of mysql
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE

If you are just trying to retrieve the results, use the following:
SELECT CURDATE() - INTERVAL stamp -1 DAY FROM myTable

Related

query for time in mysql between hours

how to get a list of rows that is between 17:30 till tomarrow 8:30.
--------------------------------------
| id | user_id | action | time |
--------------------------------------
| 1 | 25 | enter | 1512459905
| 2 | 19 | exit | 1512125105
| 3 | 31 | enter | 1514581905 |
--------------------------------------
mysql table have a time column with unix timestamp and i want get a list every day that between 17:30 till 8:30
SELECT TIME_TO_SEC(TIMEDIFF(FROM_UNIXTIME('time 1'), FROM_UNIXTIME('time 2')) AS 'time_diff_in_sec' FROM 'your_table';
This can help:
Mysql Get Time Diff
$dateStart=strtotime(date("Y-m-d 17:30:00"));
$dateEnd=strtotime(date("Y-m-d 20:30:00"));
This is how you can convert your date into unix timestamp in php.
Then in your query:
SELECT * FROM my_table WHERE time BETWEEN '$dateStart' AND '$dateEnd'
If you don't want to execute your script manually every day you can set up a cronjob to do it for you.
You can use the TIME() function to extract the time part of the datatime,
So you can do something like this:
select * FROM table t
where TIME(f.time) between '17:30:00' AND '18:30:00'

Filling in the date gaps mysql query for ajax call [duplicate]

This question already has answers here:
What is the most straightforward way to pad empty dates in sql results (on either mysql or perl end)?
(9 answers)
Closed 5 years ago.
What is the best way to include empty dates for a time series graph generated from a mysql db.
If I run a query to get say all of the red cars sold on a particular day I could run :
SELECT count(car_sale_order) as 'count', DATE(sale_date) as 'sale_date'
FROM car_sales
WHERE colour = "red";
but the results could have date holes in them i.e.
------------------
count | sale_date
------------------
2 | 2017-09-03
10 | 2017-09-04
1 | 2017-09-07
23 | 2017-09-09
45 | 2017-09-10
2 | 2017-09-11
21 | 2017-09-12
when what id really like is :
------------------
count | sale_date
------------------
2 | 2017-09-03
10 | 2017-09-04
0 | 2017-09-05
0 | 2017-09-06
1 | 2017-09-07
0 | 2017-09-08
23 | 2017-09-09
45 | 2017-09-10
2 | 2017-09-11
21 | 2017-09-12
I use PHP so know that i could generate this stuff at that side but it would be really handy to just have the result set include this from the get go....
This isn't the same as What is the most straightforward way to pad empty dates in sql results (on either mysql or perl end)?
I'm looking for a MySQL only result
Consider using a calendar table. I have always found this to be the most reliable way to create date reports as you have a row for every date which you join with your table. In your case, you may wish to use something like:
SELECT count(car_sale_order) as 'count', DATE(sale_date) as 'sale_date'
FROM calendar_table
LEFT JOIN car_sales ON calendar_table.date = car_sales.sale_date
WHERE calendar_table.date BETWEEN '2017-01-01' and '2017-01-31' and colour = "red";

MySQL - selecting the correct data within the correct week using week beginnings

I am trying to select data, when inserting the data it has an auto insert of the date when submitting. So when data is inserted it inserts the current date.
However, in my table I have week beginnings, so I am trying to select the data inside of that week:
mysql> select * from week;
+---------+------+------------+
| week_id | week | date |
+---------+------+------------+
| 1 | 1 | 2014-12-29 |
| 2 | 2 | 2015-01-05 |
| 3 | 3 | 2015-01-12 |
| 4 | 4 | 2015-01-19 |
| 5 | 5 | 2015-01-26 |
| 6 | 6 | 2015-02-02 |
| 7 | 7 | 2015-02-09 |
| 8 | 8 | 2015-02-16 |
| 9 | 9 | 2015-02-23 |
| 10 | 10 | 2015-03-02 |
| 11 | 11 | 2015-03-09 |
| 12 | 12 | 2015-03-16 |
| 13 | 13 | 2015-03-23 |
| 14 | 14 | 2015-03-30 |
| 15 | 15 | 2015-04-06 |
| 16 | 16 | 2015-04-13 |
| 17 | 17 | 2015-04-20 |
e.g.
select * from table where date='2015-04-06';
However the data will not be selected and presented because the inserted date was 2015-04-10. The only way to retrieve that data is by doing this:
select * from table where date='2015-04-10'; < when the data was inserted
So my question is, is it possible to select that data from that week beginning?
So if I select data from 2015-04-06 it should show data from the range of 2015-04-06 to 2015-04-12, is that possible?
Hopefully I have explained correctly, been a bit tricky to explain let alone try to implement. I can add any more info if needed.
NOTE: I am trying to use this inside of PHP so where the date is I would just use a variable, just thought I would say.
As the week will always end 6 days from the beginning you can use the between operator and the date_add function like this:
(for your specific example):
select *
from table
where date between '2015-04-06' and date_add('2015-04-06', interval 6 day)
And using a php variable:
select *
from table
where date between '$name_of_dt_var' and date_add('$name_of_dt_var', interval 6 day)
You could also compare the week of the date the data was entered with the weeks in the week table using WEEK() function.
Assuming that week is the same value as week(), the:
select t.*
from table t
where week = week('2015-04-10');
Even if the numbers do not match, then presumably you have some base date (such as 2015-01-01 and simple arithmetic would accomplish something very similar).
I have found that the most robust way to do this sort of week processing is to truncate each date in the table (in your example 2015-04-10) to the preceding Monday at midnight. That way you can compute the week of each item by assigning it to the first day of that week.
This little formula returns the preceding Monday given any DATE or DATETIME value.
FROM_DAYS(TO_DAYS(datestamp) -MOD(TO_DAYS(datestamp) -2, 7))
For example,
set #datestamp := '2015-04-10'
SELECT FROM_DAYS(TO_DAYS(#datestamp) -MOD(TO_DAYS(#datestamp) -2, 7))
yields the value 2015-04-06.
So, if you have a table called sale you can add up sales by week like this:
SELECT SUM(amount) weekly_amount,
FROM_DAYS(TO_DAYS(datestamp) -MOD(TO_DAYS(datestamp) -2, 7)) week_beginning
FROM sale
GROUP BY FROM_DAYS(TO_DAYS(datestamp) -MOD(TO_DAYS(datestamp) -2, 7))
This is a very convenient way to handle things, because it's robust over end-of-year transitions. The WEEK() function doesn't work quite as well.
If your business rules say that your weeks begin on Sunday rather than Monday, use -1 rather than -2, as follows.
FROM_DAYS(TO_DAYS(datestamp) -MOD(TO_DAYS(datestamp) -1, 7))

Date between 2 other dates, disregarding year

I'm looking for something like the person here was lookin for, only I'd like to use MySQL. The table below is something you'd find in my database (simplified).
+------+------+------+------+
| id | name | first| last |
+------+------+------+------+
| 1 | John | 1020 | 0814 |
| 2 | Ram | 0827 | 0420 |
| 3 | Jack | 0506 | 0120 |
| 4 | Jill | 0405 | 0220 |
| 5 | Zara | 1201 | 1219 |
+------+------+------+------+
First of all the entry has to be random, not id 4 and I only want 1 entry. I worked that out: SELECT * FROM test WHERE id <> 4 ORDER BY rand() LIMIT 1.
In this table the columns 'first' and 'last' are dates formatted as mmdd (both integers). So John is available for most of the year; from October 20th to August 14th. Zara on the other hand is only available for a small period of time; December 1st till December 19th.
My question: how do I change my query to only select the available people? I can't use 'between' since, in John's case, there's nothing between 1020 and 0814.
I just can't figure it out, there's must be other people that have a similar problem... Does anyone have a solution?
Kind regards
You need to distinguish two cases.
When first < last, the dates are in the same year. You can then use between to match dates.
When first > last, it means last is in the next year. In this case, the dates that match are date >= first OR date <= last.
So your WHERE clause should be:
WHERE IF(first < last, #date BETWEEN first AND last,
#date >= first OR date <= last)

MySQL sql query LIKE to get current opening hours

So, in my mysql database I am storing days and hours open in one field, called days, the data is stored in the following format:
[Monday:9:17[Tuesday:9:17[Wednesday:10:18[
As you may've guessed, it goes: [Day:From:Till and brackets are just seperatars for PHP to distinguish how many days are there.
I've been thinking all day what query would be but I could not figure out, so basically I need to get current date and time using PHP:
date(l); // Day in full text representation.
date(G); // current hour in 24 hour format.
So basically I need a query which in simple english would sound like:
SELECT all FROM businessdetails WHERE column date CONTAINS [current date] and :#:# numbers to be less than current hour and greater than current hour.
Help? My brain is melting by now.
So honestly the best thing to do is to normalize your database so you can do better queries. BUT I love to see if I can solve impossible situations so here is what you can do!
This will check all the business that are open on Tuesday at 11am
SELECT * FROM `businessdetails` WHERE `date` REGEXP 'Tuesday:(0|1|2|3|4|5|6|7|8|9|10|11):(11|12|13|14|15|16|17|18|19|20|21|22|23)[^0-9]'
(Funny thing I've found I can't seem to escape the [ in the column so I had to make sure the Regex doesn't have any extra digits at the end or it may erroneously match 2 and 20 or something.)
Here's how you can generate that REGEXP string via PHP:
<?php
$regexp = date('l') . ':(' . join('|', range(0, date('G'))) . '):(' . join('|', range(date('G'), 23)) . ')[^0-9]';
DISCLAIMER I don't actually recommend doing this but I thought it was clever and wanted to share since it directly answers your question.
EDIT
Just noticed you changed your answer. below may not apply anymore, but I'll leave it for future reference...
I would suggest having a separate child table for this.
STORES
auto increment ID
|
| the store name the store description etc..
| / / /
.--------------------------------------------------.
| id | name | description | etc |
|--------------------------------------------------|
| 1 | mary's kitchen | a fancy restaurant | etc |
| 2 | willow creek inn | we serve breakfast | etc |
'--------------------------------------------------'
STORE_HOURS
auto increment ID
| The STORES.id
| / the day (0-SUN, 6-SAT)
| _________/ / the 24h time OPEN (HH:MM:SS *TIME*)
| / _________/ ____/ the 24h time CLOSE (HH:MM:SS *TIME*)
| / / / /
.----------------------------------------------.
| id | store_id | day | time_open | time_close |
| 1 | 1 | 1 | 08:30:00 | 20:00:00 |
| 2 | 1 | 2 | 08:30:00 | 20:00:00 |
| 3 | 1 | 3 | 10:30:00 | 20:00:00 |
| 4 | 1 | 4 | 11:00:00 | 20:00:00 |
| 5 | 1 | 5 | 08:30:00 | 22:30:00 |
'----------------------------------------------'
Now, depending on what you want to display, you could query the table:
SELECT
stores.name AS store_name,
stores.description AS store_description,
store_hours.day AS store_hours_day,
TIME(store_hours.time_open) AS store_open,
TIME(store_hours.time_close) AS store_close
FROM
stores
JOIN
store_hours
ON
store_hours.store_id = stores.id
Result: http://sqlfiddle.com/#!2/e6872/8/0
With this table structure and relationship, you can then create granular queries without too much effort.
So this might be a hell of a response, but here is one way to do it... (Although I'm sure there must be more significantly better ways:
$day = date(l); // Day in full text representation.
$time = date(G); // current hour in 24 hour format.
$sql = "SELECT businessID FROM (SELECT SUBSTRING_INDEX(t_time,':',1) as start, SUBSTRING_INDEX(LEFT(t_time,POSITION('[' IN t_time) - 1), ':',-1) as end,businessID from (SELECT SUBSTRING_INDEX(SUBSTR(`column_date`,POSITION('$day' IN `column_date`) + LENGTH('" . $day . "') + 1),':',2) as t_time, businessID from `businessdetails ` where `column_date` like '%$day%') as t_table_1) as t_table_2 where start >= $time && end <= $time";
Hopefully that works =)
PS If you need help there are all these string functions you could use:
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html

Categories