displaying available time by comparing 2 tables with a POST variable - mysql

these are my tables
RESERVATIONS
+--------+--------------------+-----------------+
| id | reservation_date | reservation_time|
+--------+--------------------+-----------------+
| 1 | November 05, 2019 | 9:00am-12:00pm |
| 2 | November 05, 2019 | 12:00pm-3:00pm |
| 3 | November 05, 2019 | 3:00pm-6:00pm |
| 4 | November 05, 2019 | 6:00pm-9:00pm |
| 5 | November 06, 2019 | 9:00am-12:00pm |
| 6 | November 06, 2019 | 12:00pm-3:00pm |
| 7 | November 06, 2019 | 3:00pm-6:00pm |
| 8 | November 12, 2019 | 9:00am-12:00pm |
| 9 | November 13, 2019 | 9:00am-12:00pm |
+--------+--------------------+-----------------+
reservation_date is in VARCHAR format
TIME_AVAILABILITY
+--------+------------------+
| id | reservation_time |
+--------+------------------+
| 1 | 9:00am-12:00pm |
| 2 | 12:00pm-3:00pm |
| 3 | 3:00pm-6:00pm |
| 4 | 6:00pm-9:00pm |
+--------+------------------+
so here's the thing, I want to display the values in my TIME_AVAILABILITY table based on a $_POST variable and RESERVATIONS table. For example if a user's input is November 05, 2019 It will display nothing because all the values in TIME_AVAILABILITY table are already in the RESERVATIONS table, but if the user input is November 06, 2019 it will only display 6:00pm-9:00pm
I tried using INNER JOIN but I just can't make it work

The TIME_AVAILABILITY table joined to a subquery of the RESERVATIONS table will produce only the null matches (which is what you are looking for since null represents a TIME_AVAILABILITY that has not been filled for the date put in the where clause your "POST" date as it were):
select t.reservation_time
from TIME_AVAILABILITY t
left join (
select reservation_time, reservation_date
from RESERVATIONS
where reservation_date = 'November 05, 2019'
) as q
on t.reservation_time = q.reservation_time
where q.reservation_date is null;

Alternative to above answer you can do it with not in clause.
select t.reservation_time
from TIME_AVAILABILITY t where t.reservation_time not in (
select reservation_time
from RESERVATIONS
where reservation_date = 'November 05, 2019'
)

Related

MySQL - How do I change the format of a date which is using the mediumtext data type?

How do I change the format of a date which is using the mediumtext data type? I can't find a solution anywhere.
From:
+-------------+----------------------------+
| Page Name | Last Modified (mediumtext) |
+-------------+----------------------------+
| Page Name 1 | Jul 20, 2018 16:06 |
| Page Name 2 | Jun 04, 2019 11:16 |
| Page Name 3 | Sep 03, 2019 13:11 |
| Page Name 4 | Sep 19, 2019 14:00 |
| Page Name 5 | Dec 20, 2019 09:34 |
+-------------+----------------------------+
To:
+-------------+----------------------+
| Page Name | Last Modified (date) |
+-------------+----------------------+
| Page Name 1 | 2018-07-20 |
| Page Name 2 | 2019-06-04 |
| Page Name 3 | 2019-09-03 |
| Page Name 4 | 2019-09-19 |
| Page Name 5 | 2019-12-20 |
+-------------+----------------------+
Select Statement:
Select PageName, LastModDate from Content
I have tried using the below code but they return Null.
- CONVERT(LastModDat, DATETIME)
- DATE_FORMAT(LastModDat, "%Y-%m-%d")
You can use str_to_date() in MySQL:
select str_to_date(left(last_modified, 13), '%M %d, %Y')
This produces a date value. I do NOT recommend converting this to a string.

How to JOIN a table based on month

I am trying to get the number of appointments for each month.
The results are grouped into each month for a rolling-12-months graph.
I have the following Query:
SELECT a.time AS appointmentdatetime,
m.text AS ref_month_text,
m.month AS ref_month_int,
YEAR(TIME) AS appointmentyear,
COUNT(a.id) AS COUNT
FROM ref_months m LEFT JOIN
appointment a
ON m.month = MONTH(a.time) AND
a.time >= DATE_ADD(NOW(), INTERVAL - 12 MONTH)
AND a.dealershipid = '1' AND a.dealerstatus != 'No-Show'
GROUP BY m.month
ORDER BY appointmentyear ASC, m.month ASC
This is the result:
+----------------+--------------------+-------+--+
| ref_month_text | appointmentyear | COUNT | |
+----------------+--------------------+-------+--+
| February | 2019 | 16 | |
| March | 2019 | 18 | |
| April | 2019 | 10 | |
| May | 2019 | 15 | |
| June | 2019 | 18 | |
| July | 2019 | 10 | |
| August | 2019 | 12 | |
| September | 2019 | 20 | |
| October | 2019 | 7 | |
| November | 2019 | 13 | |
| December | 2019 | 7 | |
| January | 2020 | 11 | |
+----------------+--------------------+-------+--+
The grouping by month, on a rolling-12-months, and showing null when no data, is what I am getting, but the issue I am having is that the count is wrong for each month.
Eg. March 2019 should be 20.
I have tried all variations of JOIN types. But still returning wrong figures.
I simplified your query
SELECT
YEAR(a.time) AS year,
ANY_VALUE(MONTHNAME(a.time)) AS month,
ANY_VALUE(COUNT(a.id)) AS counter,
MONTH(a.time) AS mo
FROM
appointment AS a
GROUP BY
year,mo
ORDER BY
year ASC,
mo ASC

How to delete duplicate data from MySQL except latest data

I want to delete records from mysql table
I have table like this
I am checking here if (date, url, price, hotelName) is same then remove except one
id | hotelName | price | url | date |
-------------------------------------------------
1 | abcd | 20$ | abcd.com | 21 jan 2019 |
2 | abcd | 24$ | abcd.com | 22 jan 2019 |
3 | wzyz | 10$ | wzyz.com | 21 jan 2019 |
4 | abcd | 20$ | abcd.com | 21 jan 2019 |
5 | wzyz | 15$ | wzyz.com | 22 jan 2019 |
6 | wzyz | 15$ | wzyz.com | 22 jan 2019 |
In this table you can see duplicate records is id [1,4] and [5,6]
I want to delete duplicate records from this table except latest data
After deleting this table should look like
id | hotelName | price | url | date |
-------------------------------------------------
2 | abcd | 24$ | abcd.com | 22 jan 2019 |
3 | wzyz | 10$ | wzyz.com | 21 jan 2019 |
4 | abcd | 20$ | abcd.com | 21 jan 2019 |
6 | wzyz | 15$ | wzyz.com | 22 jan 2019 |
If your table is not too big, this is a short and straight-forward syntax :
DELETE t1
FROM
mytable t1
CROSS JOIN t2
WHERE
t1.id < t2.id
AND t1.hotelName = t2.hotelName
AND t1.date = t2.date
AND t1.url = t2.url
AND t1.price = t2.price
Anoter solution, less resource-consuming :
DELETE FROM mytable
WHERE id NOT IN (
SELECT MAX(t.id) FROM mytable t GROUP BY t.hotelName, t.date, t.url, t.price
)
I strongly recommend group by and join for this purpose:
delete t join
(select date, url, price, hotelName, max(id) as max_id
from t
group by date, url, price, hotelName
) tt
using (date, url, price, hotelName)
where t.id < tt.max_id;
I assume by latest, you mean "keep the one with the largest id".
If you have a large amount of data, delete can be expensive. In that case. create temporary table/truncate/insert might have better performance.

Incorrect results for year,month grouping for mysql count

I am having an issue with incorrect counts for a query which is as follows:
mysql> SELECT DATE_FORMAT(FROM_UNIXTIME(timestamp), '%M') AS month,
YEAR(FROM_UNIXTIME(timestamp)) AS year, count(*) AS count FROM table1 WHERE
result LIKE '%created%' GROUP BY YEAR(FROM_UNIXTIME(timestamp)),
MONTH(FROM_UNIXTIME(timestamp)) DESC;
+-----------+------+-------+
| month | year | count |
+-----------+------+-------+
| September | 2011 | 1 |
| December | 2013 | 393 |
| November | 2013 | 70 |
| September | 2014 | 233 |
| August | 2014 | 739 |
| July | 2014 | 691 |
| June | 2014 | 618 |
| May | 2014 | 120 |
| March | 2014 | 272 |
| February | 2014 | 528 |
| January | 2014 | 607 |
+-----------+------+-------+
11 rows in set (0.40 sec)
However, when I check my work by using another syntax I get different results:
mysql> select count(*) from table1 where result like '%created%' and
timestamp >= unix_timestamp('2014-07-01') and timestamp <= unix_timestamp('2014-07-31');
+----------+
| count(*) |
+----------+
| 662 |
+----------+
1 row in set (0.39 sec)
What is wrong with the syntax?
In the second query use < unix_timestamp('2014-08-01'). I think you filter out everything that happened after 2014-07-31 00:00:00 am. There are still 24 hours in that day that shouldn't be filtered.

where clause sql and display NULL values

I have a database with information about several servers :
mysql> select DATE_FORMAT(timestamp,'%M %Y') as 'Mois',AVG(value_perf) as 'moy' from info WHERE server = 'pi4' GROUP BY MONTH(timestamp);
+----------------+-----------+
| Mois | moy |
+----------------+-----------+
| June 2014 | 98.465500 |
| July 2014 | 98.854516 |
| August 2014 | 98.227097 |
| September 2014 | 95.008667 |
| October 2014 | 77.880000 |
+----------------+-----------+
5 rows in set (0.00 sec)
However, each pi server has different starting date ( pi4 stats in june, but pi1 stats in january)
Example :
mysql> select DISTINCT DATE_FORMAT(timestamp,'%M %Y') as 'Mois' from info ORDER BY timestamp;
+----------------+
| Mois |
+----------------+
| January 2014 |
| February 2014 |
| March 2014 |
| April 2014 |
| May 2014 |
| June 2014 |
| July 2014 |
| August 2014 |
| September 2014 |
| October 2014 |
+----------------+
And i would like a query to get the average score per server, BUT with the most large view, including NULL.
Example for pi4 :
+----------------+-----------+
| Mois | moy |
+----------------+-----------+
| January 2014 | NULL |
| February 2014 | NULL |
| March 2014 | NULL |
| April 2014 | NULL |
| May 2014 | NULL |
| June 2014 | 98.465500 |
| July 2014 | 98.854516 |
| August 2014 | 98.227097 |
| September 2014 | 95.008667 |
| October 2014 | 77.880000 |
+----------------+-----------+
Ps : Here is an example of the database structure
mysql> select * from info limit 10;
+----+------------+-----------+------------+-------------+
| id | timestamp | server | value_perf | value_avail |
+----+------------+-----------+------------+-------------+
| 45 | 2014-06-11 | pi4 | 98.33 | 99.91 |
| 46 | 2014-06-12 | pi4 | 97.92 | 100.00 |
| 52 | 2014-06-18 | pi4 | 98.15 | 99.97 |
| 54 | 2014-06-20 | pi | 98.33 | 99.94 |
+----+------------+-----------+------------+-------------+
and i want the average per month, with NULL value for unavailable months.
How can i get this ?
Thanks
The simplest way to achieve what you want is to create a date lookup table. Something like
CREATE TABLE `month_lookup` (
`month_year` varchar(30),
`st` datetime,
`en` datetime,
PRIMARY KEY (`month_year`),
KEY `st` (`st`)
KEY `end` (`end`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Then insert data for each month's start and end date. Go ahead and populate it for 1970 to 2070 or something. This table can come in handy. An example row would look like
month-year st en
Jan-2014 2014-01-01 00:00:00 2014-01-31 23:59:59
Then what you can do is something like this:
SELECT a.month_year, avg(b.value_perf) AS moy
FROM month_lookup AS a
LEFT JOIN info AS b
ON b.timestamp BETWEEN a.st AND b.en
GROUP BY a.month_year, b.server;
The indices on the month_lookup table might be better if you did st_end (st, en) instead of st and en separately, but you'd have to test that... I don't recall off the top of my head if a compound index would help you with with a join ... between clause or not
Either way, create a month_lookup table and use it in a left join... probably your best option. Otherwise you'll be doing unions ond subqueries and it'll just get hard to manage.