I'm building upon a solution I developed a while ago - ticket booking. I now need to add a feature to allow tickets to be "held" during purchasing to make them appear as sold to another customer coming to the site (preventing double-booking).
Details on the original tables are in my previous question, MySQL - Trying to count tickets sold for an event. The tickets table now has a held_until DateTime value, and a paid tinyint (bool) value.
I need the events.capacity - COUNT(tickets.id) AS available to now only count those tickets which either:
Have a paid value of 1
Have a paid value of 0 and held_until > now()
I've tried adding WHERE and HAVING clauses, but these prevent events where no tickets have been sold from showing. I also had a play around with nested queries but didn't get anywhere with that either...
Any suggestions?
Modify Andomar's suggested query (in the other topic) as below :
change
ON events.id = tickets.event_id
to
ON ( events.id = tickets.event_id AND ( tickets.paid = 1 OR tickets.held_until > now() )
Even if all the required information can be found in your other topic, it would probably have been a good idea to repeat some relevant details here.
Related
I am trying to build a SELECT statement on a MySQL view that will end up as a resource on a calendar app. Clients are booking out a piece of equipment for a period of time (bookings). Payment (payments) is taken at the beginning of the hire period for the equipment but further payments can be made if the hire period is extended. Therefore a single booking will have one, possibly many payments associated with it. Payments are recorded with the amount paid and the date they are paid.
Bookings for equipment must appear on the calendar if the date being viewed is within the hire period. Also, and this is the part I am having trouble with, payments, if they have been made on the date viewed, must be displayed (the reason for this is that my customer wants a daily total of takings for hires). If they haven't made a payment on the date viewed then the amount must appear as 0.
My view is built from three tables - bookings, payments and clients. The clients table is unimportant in this problem as it is just used in the view to generate the client name to be displayed on the calendar.
[![bookings][1]][1]
[![payments][2]][2]
The view is shown below
[![view_bookings_detail][3]][3]
This is what I am attempting to achieve. When the user opens the calendar or changes the calendar date, that date is used in my resource SELECT query as a parameter. In the first example we are viewing 04/07/2022. The parameter [selected_date] is set to '2022-07-04'. My initial SELECT statement was -
SELECT client_id, title, longterm_fee FROM view_bookings_detail WHERE start_date <= '[selected_date]' AND end_date >= '[selected_date]'
This returns -
[![calendar resource feed][4]][4]
Clearly this is no good as it would result in multiple entries for both hirer's. If I amend the select statement to -
SELECT client_id, title, longterm_fee FROM view_bookings_detail WHERE start_date <= '[selected_date]' AND end_date >= '[selected_date]' AND ltf_paid_on = '[selected_date]'
This returns -
[![amended calendar resource feed][5]][5]
This returns what I want but only because the two hirer's made payments on 04/07/2022.
If I were to view 05/07/2022, for instance, using the above logic, no records would be selected as no payments were made on 05/07/2022. What I would need returned in this case is a single record for each hirer with the longterm_fee showing as 0
I don't know how to achieve this. Anyone any ideas please?
I have the dataset in the image
105665 Status changed 03-2017, Decommissioned from the prior month of 02-2017, Pending Decommissioned.
On a monthly basis, I need to determine which Assets have changed Status from the "prior" month. I was thinking a new field is needed that tells me which Assets have changed status from the prior month but don't know how to determine that logic. I will also need a count of Assets of how many moved from Pending Decommissioned to Decommissioned for example or from Installed to Pending Decommissioned but I'll worry about that part later.enter image description here
(I have found similar cases but not exactly like this one so although I still tried those solutions, none of them worked for me).
Many thanks!
In your status table, you can join to the prior month, showing those rows that have a different value. Below assumes your dates are not text.
Select tm.asset
, tm.date
, lm.date
, tm.status
, lm.status
from table tm
inner join table lm
on tm.date = lm.date - INTERVAL 1 MONTH
and tm.asset = lm.asset
I am developing a php/mysql database.
I have a table called ‘actions’ which (amongst others) contains fields hrs, mins, actiondate, invoiceid and staffid.
For any particular actiondate there could be any number of actions carried out by various staff who would enter their time as hrs and mins.
What I need to do is produce a table which for each date and for a specific member of staff and invoice, adds up all of the hrs and mins for each date as a decimal, rounds it up to the nearest quarter and displays that result. I also need to be able to add up all of those results and display that total.
For example, if on March 1st, person with staffid=23 had carried out 4 actions for invoiced 121 lasting, 1h2m, 23m, 10m and 20m the total for that day would be 62+23+10+20 = 115m = 115/60 = 1.92 which would be rounded up to 2.00.
I can get each day’s total (maybe not very elegantly) and display it against the date using the code below
SELECT actions.`actiondate`,
(FORMAT((((CEIL((((60*SUM(hrs))+SUM(mins))/60)*4))/4)),2)) AS dayfeeqtr
FROM actions
WHERE staff.staffid=’23’
AND invoiceid=‘121’
GROUP BY actions.`actiondate`
However, what I can’t work out, is how can I add up all of these rounded up results for that invoice and that member of staff.
Can anyone help please?
If I understand correctly, you can use a subquery:
SELECT sum(dayfeeqtr)
FROM (SELECT a.`actiondate`,
FORMAT((((CEIL((((60*SUM(hrs))+SUM(mins))/60)*4))/4)), 2) AS dayfeeqtr
FROM actions a
WHERE s.staffid = '23' AND invoiceid = '121'
GROUP BY a.`actiondate`
) a;
I do note that your query is not correct -- for instance, there is a reference to staff, which is not in a from clause. However, you say that this is working, so I assume the errors are a transcription problem.
In rails 3 (also with meta_where gem if you feel like using it in your query), I got a really tricky query that I have been banging my head for:
Suppose I have two models, customers and purchases, customer have many purchases. Let's define customers with at least 2 purchases as "repeat_customer". I need to find the total number of repeat_customers by each day for the past 3 months, something like:
Date TotalRepeatCustomerCount
1/1/11 10 (10 repeat customers by the end of 1/1/11)
1/2/11 15 (5 more customer gained "repeat" status on this date)
1/3/11 16 (1 more customer gained "repeat" status on this date)
...
3/30/11 150
3/31/11 160
Basically I need to group customer count based on the date of creation of their second purchase, since that is when they "gain repeat status".
Certainly this can be achieved in ruby, something like:
Customer.includes(:purchases).all.select{|x| x.purchases.count >= 2 }.group_by{|x| x.purchases.second.created_at.to_date }.map{|date, customers| [date, customers.count]}
However, the above code will fire query on the same lines of Customer.all and Purchase.all, then do a bunch of calculation in ruby. I would much prefer doing selection, grouping and calculations in mysql, since it is not only much faster, it also reduces the bandwith from the database. In large databases, the code above is basically useless.
I have been trying for a while to conjure up the query in rails/active_record, but have no luck even with the nice meta_where gem. If I have to, I will accept a solution in pure mysql query as well.
Edited: I would cache it (or add a "repeat" field to customers), though only for this simplified problem. The criteria for repeat customer can change by the client at any point (2 purchases, 3 purchases, 4 purchases etc), so unfortunately I do have to calculate it on the spot.
SELECT p_date, COUNT(customers.id) FROM
(
SELECT p_date - INTERVAL 1 day p_date, customers.id
FROM
customers NATURAL JOIN purchases
JOIN (SELECT DISTINCT date(purchase_date) p_date FROM purchases) p_dates
WHERE purchases.purchase_date < p_date
GROUP BY p_date, customers.id
HAVING COUNT(purchases.id) >= 2
) a
GROUP BY p_date
I didn't test this in the slightest, so I hope it works. Also, I hope I understood what you are trying to accomplish.
But please note that you should not do this, it'll be too slow. Since the data never changes once the day is passed, just cache it for each day.
(In case this seems familiar: I asked a different question similar to this one, but I just got a note that the site design has changed and now the owners do want a way to search for any room that is available between a range of dates. So this is a new question...)
I'm working on a hotel reservation system and I need to find which rooms are available between a range of dates. The existing 'availability' table schema is simple, the columns are:
room_id
date_occupied - a single day that is occupied (like '2011-01-01')
So, if, for example, room #6 is occupied from January 1 to January 5, five rows are added to the availability table, one for each day that room is occupied.
I'm trying to figure out the query to find what rooms are available between a start and end date (while also filtering on some other parameters like non-smoking, bed size, etc.)... in pseudo-SQL it would be sort of like:
SELECT (a list of room IDs) FROM rooms, availability
WHERE rooms.nonsmoking = 1
AND rooms.singlebed = 1
AND nothing between start_date and end_date is in availability.date_occupied
As with my other question, I'm a bit stuck trying to determine the exact query and how to join the tables it in the most efficient way. Thanks for the help.
If I understood your db structure properly, you need to find a row in rooms with no corresponding rows in availability.
SELECT r.*
FROM rooms r
LEFT JOIN availability a ON (r.id = a.room_id
AND a.date_occupied BETWEEN :start_date AND :end_date)
WHERE a.id IS NULL