restaurant table availability check for a particular time using sql - php

I am trying to build a restaurant table management application using yii framework currently i am stuck with retrieving availability of tables for a particular time
i have the following tables
below image shows the table structure i have
i am getting the avaiable table by using the following piece of code
$model = new Table;
$criteria = new CDbCriteria;
$criteria->condition = 'floor_id=' . $floorid;
$rows = $model->model()->with(array(
'bookingTables' => array(
'condition' => 'bookingTables.table_id IS NULL'
)))->findAll($criteria);
this works only when the table ids are not present in the booking_table table
suppose if say the booking_table table has table ids filled then above code will not work it will always return as not available (no clue how to use time to get available tables)
so how can i get the available tables for a particular time period any solution in yii or sql

Since you accept both SQL and YII, I give you a solution in SQL.
If you want to check availability at a given time, you need to know the reservation date (that includes the hour), so let's consider that we add the field 'reservation_date' in your 'booking_table' table, and let's consider a booking ends 2 hours after it has started.
This is what I'll do in SQL :
SELECT t.table_id
FROM TABLE AS t
LEFT OUTER JOIN booking_table AS b ON b.booking_table_id = t.table_id
WHERE b.booking_id IS NULL
OR DATE_ADD(NOW(), INTERVAL 2 HOUR) > b.reservation_date
This query lists all available tables at the time its executed. If you want to check availability at a specific time, replace 'NOW()' by whatever you need.

Related

SQL select all files where a value in table A is the same as in table B (same database)

I'm building a sales system for a company, but I'm stuck with the following issue.
Every day I load .XML productfeed into a database called items. The rows in the productfeed are never in the same order, so sometimes the row with Referentie = 380083 is at the very top, and the other day that very same row is at the very bottum.
I also have to get all the instock value, but when I run the following query
SELECT `instock` FROM SomeTable WHERE `id` > 0
I get all values, but not in the same order as in the other table.
So I have to get the instock value of all rows where referentie in table A is the same as it is in table B.
I already have this query:
select * from `16-11-23 wed 09:37` where `referentie` LIKE '4210310AS'
and this query does the right job, but I have like 500 rows in the table.
So I need to find a way to automate the: LIKE '4210310AS' bit, so it selects all 500 values in one go.
Can somebody tell me how that can be done?
I'm not even sure I understand your problem...
Don't take this personally, but you seem to be concerned/confused by the ordering of the data in the tables which suggests to me your understanding of relational databases and SQL is lacking. I suggest you brush up on the basics.
Can't you just use the following query?
SELECT a.referentie
, b.instock
FROM tableA a
, tableB b
WHERE b.referentie = a.referentie

MySQL select unused/stale id based on timestamp period

I have an attendance table with simple .user and .timestamp and want to identify any .user without a timestamp since a specific time (eg 1 year ago).
I have tried several combinations of between and is not between etc., but can't seem to get the correct output (my logic and SQLs is obviously different :( )
The want to remove 'stale' users (haven't attended for a year). Once I have the data from the attendance table I will use that to delete records from other tables containing their details.
To Delete:
DELETE FROM userattendance WHERE user_id IN (SELECT user_id FROM users WHERE mytimestamp < (UNIX_TIMESTAMP() - 31557600))
It's pretty much saying DELETE data from the user attendance table where mytimestamp field is less than the current unix timestamp minus a year for any user.

How to program a recurring billing/invoice system using PHP and MySQL

I have already programmed a basic invoicing system using PHP/MySQL which has a table structure as follows;
Invoice table; invoice_id, invoice_date, customer_id, etc
Invoice line table; invoice_line_id, invoice_id, quantity, price, description, etc
I need the system to automatically generate future invoices at set intervals (for example every 1 week or every 2 months, etc). I was thinking of creating a new table as follows;
Invoice schedule table; invoice_schedule_id, invoice_id, interval (e.g. 1), interval_unit (months), start date, next_processing_date
My idea was to then setup a cron job which would execute a PHP file once a day. The PHP file would then generate an invoice when the next_processing_date matched today's date and update the next_processing_date in the database. I'm comfortable on how to achieve this but what I'm stuck with is how to actually insert the new invoice into the table/database. Does MySQL have any type of 'copy row' feature as the new invoice would be identical to the original one except for the invoice_date having to be updated.
Cron sounds good. (Also it is worth to mention the MySQL Event Scheduler, but again I would go for a Cronjob)
A copy would be something like this SQLFIDDLE:
create table t ( id int, d date );
insert into t values( 0, CURDATE() );
insert into t values( 2, CURDATE() );
insert into t values( 1, CURDATE() );
insert into t ( select id+1,curdate() from t order by id desc limit 1 );
Above example is to copy the latest order as a copy, of course you could put a where clause where id=1 or what id your reference order is.
BigScar's reference of "How to copy a row and insert in same table with a autoincrement field in MySQL?" seems to solve your copy-insert problem.
However, since you are mostly doing a specific group of DB queries, instead of cronjobs, you may use MySQL events. If your MySQL version supports them (check in phpmyadmin: select a DB and look to the top menu bar, you can create them there without even have to know the syntax), it's a good practical alternative.

JOIN query too slow on real database, on small one it runs fine

I need help with this mysql query that executes too long or does not execute at all.
(What I am trying to do is a part of more complex problem, where I want to create PHP cron script that will execute few heavy queries and calculate data from the results returned and then use those data to store it in database for further more convenient use. Most likely I will make question here about that process.)
First lets try to solve one of the problems with these heavy queries.
Here is the thing:
I have table: users_bonitet. This table has fields: id, user_id, bonitet, tstamp.
First important note: when I say user, please understand that users are actually companies, not people. So user.id is id of some company, but for some other reasons table that I am using here is called "users".
Three key fields in users_bonitet table are: user_id ( referencing user.id), bonitet ( represents the strength of user, it can have 3 values, 1 - 2 - 3, where 3 is the best ), and tstamp ( stores the time of bonitet insert. Every time when bonitet value changes for some user, new row is inserted with tstamp of that insert and of course new bonitet value.). So basically some user can have bonitet of 1 indicating that he is in bad situation, but after some time it can change to 3 indicating that he is doing great, and time of that change is stored in tstamp.
Now, I will just list other tables that we need to use in query, and then I will explain why. Tables are: user, club, club_offer and club_territories.
Some users ( companies ) are members of a club. Member of the club can have some club offers ( he is representing his products to the people and other club members ) and he is operating on some territory.
What I need to do is to get bonitet value for every club offer ( made by some user who is member of a club ) but only for specific territory with id of 1100000; Since bonitet values are changing over time for each user, that means that I need to get the latest one only. So if some user have bonitet of 1 at 21.01.2012, but later at 26.05.2012 it has changed to 2, I need to get only 2, since that is the current value.
I made an SQL Fiddle with example db schema and query that I am using right now. On this small database, query is working what I want and it is fast, but on real database it is very slow, and sometimes do not execute at all.
See it here: http://sqlfiddle.com/#!9/b0d98/2
My question is: am I using wrong query to get all this data ? I am getting right result but maybe my query is bad and that is why it executes so slow ? How can I speed it up ? I have tried by putting indexes using phpmyadmin, but it didn't help very much.
Here is my query:
SELECT users_bonitet.user_id, users_bonitet.bonitet, users_bonitet.tstamp,
club_offer.id AS offerId, club_offer.rank
FROM users_bonitet
INNER JOIN (
SELECT max( tstamp ) AS lastDate, user_id
FROM users_bonitet
GROUP BY user_id
)lastDate ON users_bonitet.tstamp = lastDate.lastDate
AND users_bonitet.user_id = lastDate.user_id
JOIN users ON users_bonitet.user_id = users.id
JOIN club ON users.id = club.user_id
JOIN club_offer ON club.id = club_offer.club_id
JOIN club_territories ON club.id = club_territories.club_id
WHERE club_territories.territory_id = 1100000
So I am selecting bonitet values for all club offers made by users that are members of a club and operate on territory with an id of 1100000. Important thing is that I am selecting club_offer.id AS offerId, because I need to use that offerId in my application code so I can do some calculations based on bonitet values returned for each offer, and insert data that was calculated to the field "club_offer.rank" for each row with the id of offerId.
Your query looks fine. I suspect your query performance may be improved if you add a compound index to help the subquery that finds the latest entry from users_botinet for each user.
The subquery is:
SELECT max( tstamp ) AS lastDate, user_id
FROM users_bonitet
GROUP BY user_id
If you add (user_id, tstamp) as an index to this table, that subquery can be satisfied with a very efficient loose index scan.
ALTER TABLE users_bonitet ADD KEY maxfinder (user_id, tstamp);
Notice that if this users_botinet table had an autoincrementing id number in it, your subquery could be refactored to use that instead of tstamp. That would eliminate the possibility of duplicates and be even more efficient, because there's a unique id for joining. Like so.
FROM users_botinet
INNER JOIN (
SELECT MAX(id) AS id
FROM users_botinet
GROUP BY user_id
) ubmax ON users_botinet.id = ubmax.id
In this case your compound index would be (user_id, id.
Pro tip: Don't add lots of indexes unless you know you need them. It's a good idea to read up on how indexes can help you. For example. http://use-the-index-luke.com/

Finding events in a MySQL table, manipulating and storing the data

This is question I have still not been able to resolve, so maybe I need to be clearer in what I need.
I have a datasource which I receive and upload to a MySQL database each month. I cannot alter the data although it may not be in the most helpful format. It looks like this:
Ref Action Date/Time User Location
00123 Create 01:02:12_09:13:13 J Jones Home
00456 Create 01:02:12_09:13:13 J Jones Home
00123 Revise 03:02:12_15:20:01 A Smith Home
00789 Create 01:02:12_09:13:13 J Jones Home
00123 Delete 05:02:12_10:51:45 B Halls Home
x 1000's
It tracks events that occur against a reference number, which is generated by the first event (the Create event). These events occur at varying intervals and are done by various people in various locations.
Using the above example I need to be able to loop through the data for a particular month, pull out a reference number and its 'Create' event, then locate all the other events for that ref number.
I then need to be able to manipulate this information, for example calculate the time difference between Create and Revise, and then Revise and Delete, and who did them, where.
I need to be able to this for all the ref numbers created in the month or a date range.
So I am hoping I can create a query that can do this - find a ref number, find the other events, string them together in some way - so that in the end I have new data -
Ref Number, Time of Create, Create By Who, Time of Revise/By Who, Time of Delete etc
It would be useful if this new data could be stored in a new table, I would think(?)
Can this be done as a query or perhaps combination of query and PHP (arrays?)
Okay, the first stage is to transform this data in a MySQL table, and
you will have something like
ref integer,
action enum('create','revise','delete'), -- ordered by life cycle: create first, delete last
ts timestamp,
user varchar(32), -- or maybe user_id
loc varchar(32), -- again maybe location_id, or ENUM
So to pull out an event given its reference
SELECT * FROM mytable WHERE ref = 123 ORDER BY action;
For date ranges you can use
WHERE ts BETWEEN 'date1' AND 'date2'
To get time differences,
SELECT TIMEDIFF(b.ts, a.ts) AS delta, b.*
FROM mytable AS a
JOIN mytable AS b ON (a.action = 'CREATE' AND a.ref = b.ref)
WHERE a.ref = 123;
Finally to denormalize the table:
SELECT _create.*,
TIMEDIFF(_revise.ts - _create.ts) AS revise_delta,
TIMEDIFF(_delete.ts - _delete.ts) AS delete_delta,
FROM mytable AS _create
LEFT JOIN mytable AS _revise ON (_create.ref = _revise.ref
AND _create.action = 'CREATE' AND AND _revise.action = 'REVISE' AND ***)
LEFT JOIN mytable AS _delete ON (_create.ref = _delete.ref
AND _create.action = 'CREATE' AND AND _delete.action = 'DELETE' AND ***)
;
Here * is some way of identifying the unique relation between a CREATE event and the corresponding DELETE event.
If refs are unique, then AND *** is not needed (* equals to True).
For example if the refs are recycled every month, and it never happens that an event may span two months, you can impose that the year and month of _create should be the same as those of _revise; that and the equality of .ref establish a biunivocal match.
Otherwise it gets much more complicated, and I'd try creating a VIEW that for each CREATE event selects the COALESCE of NOW() and the datetime of the earliest CREATE event with that same ref but ts greater or equal to the current. This way you identify a "window" in which events with that ref should be attributed to that specific CREATE. But this is based on the hypothesis that it never happens that
00123 CREATE 01-NOV-2012 Jack
00123 CREATE 04-NOV-2012 Jill
00123 DELETE 05-NOV-2012 Joe <-- which event is this one?
Well, to get field values for a particular action:
$db_connection = mysqli_connect();//Have DB variables here
$ref = ;//Ref number here e.g 123
$action = '';//action to check for here e.g create
$query = "SELECT * FROM yourtable WHERE ref=".$ref." AND action=".$action."";
$q = mysqli_query($db_connection,$query);
while($row = mysqli_fetch_asocc($q)){
//The variables are in the $row array with each on an index based on a column name
}

Categories