I have the following table structure:
roominfo table
+---------+----------------+---------------+
| Room_id | room_type_name | maximum_rooms |
+---------+----------------+---------------+
| 1 | A | 16 |
| 2 | B | 14 |
| 3 | C | 7 |
| 4 | D | 2 |
| 5 | E | 2 |
+---------+----------------+---------------+
bookedtable stores all the rooms booked within that date:
+------------+--------------+---------------+----------------+---------+
| room_bk_id | checkin_date | checkout_date | maxroomsbooked | room_id |
+------------+--------------+---------------+----------------+---------+
| 1 | 2014-01-28 | 2014-01-29 | 8 | 1 |
| 2 | 2014-01-29 | 2014-01-30 | 2 | 4 |
| 3 | 2014-01-28 | 2014-01-29 | 4 | 1 |
+------------+--------------+---------------+----------------+---------+
bookingprogress table to avoid the race condition (it blocks upto the expire time) I set the maximum expire time as 15 minutes from current time
+------------+----------------+-----------------+----------------+---------+---------------+---------------------+
| room_pg_id | checkinpg_date | checkoutpg_date | maxroomsbooked | room_id | sessionid | ExpireTime |
+------------+----------------+-----------------+----------------+---------+---------------+---------------------+
| 1 | 2014-01-28 | 2014-01-29 | 2 | 1 | AdsddsA23asd | 2014-01-28 00:15:00 |
| 2 | 2014-01-29 | 2014-01-30 | 2 | 5 | AdsQWerasdwe | 2014-01-28 00:18:00 |
| 3 | 2014-01-28 | 2014-01-29 | 1 | 2 | BdrtQWerasdwe | 2014-01-28 00:20:00 |
+------------+----------------+-----------------+----------------+---------+---------------+---------------------+
The workflow is:
User checks for the available rooms by providing checkin date, checkout date and no of rooms.
I need to find and display the rooms are available which are not blocked or booked for that particular period.
The executed query was (might be small mistakes -- Here I gave overview of what I have done --So modified my query according to that)
SELECT tbook.*,
SUM(tbook.maxroomsbooked + tprogress.maxroomsbooked) AS bookedrooms
FROM bookedtable AS tbook
JOIN bookingprogress AS tprogress USING (Room_id)
JOIN roominfo AS troomtype USING (Room_id)
WHERE tbook.checkout_date > '2014-01-28'
AND tprogress.checkoutpg_date > '2014-01-28'
AND tprogress.ExpireTime < '2014-01-27 00:10:00'
AND tprogress.room_id = 1
GROUP BY Room_id
From the above tables I tried to get the rooms which are available for booking. But I didn't get the expected result.
See it on sqlfiddle.
Could you please provide me with the solution?
One way would be to use NOT EXISTS subqueries. For example, if a user is interested in booking '2014-02-01' to '2014-02-07':
SELECT *
FROM roominfo r
WHERE NOT EXISTS (
SELECT *
FROM bookedtable b
WHERE b.room_id = r.room_id
AND NOT (
b.checkin_date < '2014-02-07'
AND b.checkout_date > '2014-02-01'
)
LIMIT 1
)
AND NOT EXISTS (
SELECT *
FROM bookingprogress p
WHERE p.room_id = r.room_id
AND p.ExpireTime > CURRENT_TIME
AND NOT (
p.checkinpg_date < '2014-02-07'
AND p.checkoutpg_date > '2014-02-01'
)
LIMIT 1
)
Related
I'm trying to add a new page onto an old site, a records page that'd show which players won the most money or won the race when they were a certain age
The user table looks like this
***********************************
| id | name | age | bday |
| 1 | bob | 15 | 2000-07-30 |
| 2 | john | 14 | 2001-07-30 |
| 3 | mary | 13 | 2002-07-30 |
***********************************
the race_results table looks like this
************************************************************
| id | raceid | userid | place | winnings | date |
| 1 | 1 | 1 | 1 | 1000 | 2006-04-10 |
| 2 | 1 | 2 | 5 | 50 | 2005-02-15 |
| 3 | 1 | 3 | 6 | 50 | 2010-06-12 |
| 4 | 2 | 1 | 1 | 1000 | 2009-05-29 |
| 5 | 2 | 2 | 3 | 250 | 2003-01-12 |
************************************************************
What's the most practical approach to a query that'd calculate the year range when Bob was 3 years old and match that with the race results table to see how many times he won 1st place within that particular date range?
SELECT COUNT(*)
FROM 'race_results'
INNER JOIN 'user' on user.id = race_results.userid
WHERE user.name = 'bob'
AND race_results.place = 1
AND race_results.date >= ADDDATE(user.bday, INTERVAL 3 YEAR)
AND race_results.date < ADDDATE(user.bday, INTERVAL 4 YEAR);
To get a list of all 3 yr old 1st placers and how many times they won, not just for 'bob' ...
SELECT user.name, COUNT(*)
FROM 'race_results'
INNER JOIN 'user' on user.id = race_results.userid
WHERE race_results.place = 1
AND race_results.date >= ADDDATE(user.bday, INTERVAL 3 YEAR)
AND race_results.date < ADDDATE(user.bday, INTERVAL 4 YEAR)
GROUP BY user.name;
Here is my data
cardNo| userName| tablename| hours | date
1 | a | a | 12 | 12-06-2015
1 | a | a | 5 | 11-06-2015
2 | b | b | 3 | 15-06-2015
1 | a | a | 8 | 12-06-2015
2 | b | b | 3 | 21-06-2015
1 | a | a | 12 | 14-06-2015
2 | b | b | 10 | 8-06-2015
cardNo is unique. I need to display all details and total hours for each card, like:
cardNo | userName | tablename | totalhours
1 | a | a | 37
2 | b | b | 16
It's simple SUM() with GROUP BY:
SELECT cardNo,sum(hours)
FROM yourtable
GROUP BY cardNo;
I left it as an exercise for the OP to include userName and tablename columns into the query
SELECT cardNo,userName, tablename, sum(hours) hours
FROM Table_1 GROUP BY cardNo,userName,tablename
I have got table for example
+------+--------+--------+---------------------+
| Type | Value1 | Value2 | DateAdded |
+------+--------+--------+---------------------+
| 1 | a | a | 2014-03-31 20:00:00 |
| 2 | a | a | 2014-03-31 20:00:10 |
| 3 | a | a | 2014-03-31 20:00:25 |
| 1 | a | a | 2014-03-31 20:00:40 |
| 2 | a | a | 2014-03-31 20:00:50 |
| 3 | a | a | 2014-03-31 20:00:60 |
| 1 | a | a | 2014-03-31 20:01:10 |
| 2 | a | a | 2014-03-31 20:01:25 |
| 3 | a | a | 2014-03-31 20:01:35 |
+------+--------+--------+---------------------+
and many more rows... I want to to recieve in a single query:
20 rows WHERE type = 1 ORDER BY DateAdded DESC
20 rows WHERE type = 2 ORDER BY DateAdded DESC
20 rows WHERE type = 3 ORDER BY DateAdded DESC
and there can be more than three types.
One approach to this type of query is the count(*) in a subquery approach:
select *
from table t
where 20 >= (select count(*)
from table t2
where t2.type = t.type and
t2.DateAdded >= t.DateAdded
);
Count the number of rows with the same time that have a larger DateAdded and choose the ones that have up to 20 of them.
I have the following 3 tables: unit, stage, stats.
unit stage
+----+--------+ +----+-------+---------------------+
| id | status | | id |unit_id| date |
+----+--------+ +----+-------+---------------------+
| 1 | 2 | | 1 | 2 | 2013-11-22 00:00:00 |
| 2 | 3 | | 2 | 2 | 2013-11-26 12:00:00 |
| 3 | 3 | | 3 | 3 | 2013-10-11 00:00:00 |
| 4 | 0 | | 4 | 1 | 2013-12-29 00:00:00 |
+----+--------+ +----+-------+---------------------+
stats
+----+----------+---------------------+-------+
| id | stage_id | date | clicks|
+----+----------+---------------------+-------+
| 1 | 1 | 2013-11-22 00:00:00 | 10 |
| 2 | 1 | 2013-11-23 00:00:00 | 20 |
| 3 | 1 | 2013-11-24 00:00:00 | 25 |
| 4 | 2 | 2013-11-26 00:00:00 | 15 |
| 5 | 2 | 2013-11-27 12:00:00 | 21 |
| 6 | 3 | 2013-12-29 00:00:00 | 8 |
+----+----------+---------------------+-------+
I need a request, that will produce the following response:
+---------+---------------------+-----------------------+
| unit.id | stage.min.date | sum(stats.max.clicks) |
+---------+---------------------+-----------------------+
| 2 | 2013-11-22 00:00:00 | 46 |
| 3 | 2013-12-29 00:00:00 | 8 |
+---------+---------------------+-----------------------+
by the following rules:
1) unit.id - show only units with unit.status=3
2) stage.min.date - minimal stage.date for corresponding unit_id
3) sum(stats.max.clicks) - sum of stats.clicks with max dvalues for each stage_id associated with corresponding unit_id. In my example 46 = 25(stage_id=1) + 21(stage_id=2)
The problem is in min.date and sum of clicks - I have no idea how to get it in one query. Definitely it`s not a problem to do it using php code and several requests.
Schema in SQL Fiddle
Thanks in advance.
I just ask myself, why I do this? Your example resonse has an error, and does not match your fiddle... but:
SELECT
cc.unit_id, MIN(cc.date) as stage_min_date , SUM(dd.clicks) as stats_max_clicks
FROM
stage cc
LEFT JOIN (
SELECT
bb.stage_id, bb.clicks
FROM
stats bb LEFT JOIN (
SELECT id, stage_id, MAX(date) AS max_date
FROM stats
GROUP BY stage_id
) aa
ON
aa.max_date = bb.date
WHERE
aa.max_date IS NOT NULL
) dd
ON cc.id = dd.stage_id
LEFT JOIN unit ee
ON ee.id = cc.unit_id
WHERE ee.status = 3
GROUP BY cc.unit_id
...
I want to find the three most sold products every day and
show them together with number of sales.
However if there are more than one product sharing the same
number of sales I just want to tell how many products got this
ranking.
I have two tables
Products:
+-----+---------+
| Pid | Product |
+-----+---------+
| 1 | Moon |
| 2 | Sun |
| 3 | Venus |
| 4 | Mars |
+-----+---------+
SalesRows:
+-----+---------+------------+
| Pid | No_sold | Sales_date |
+-----+---------+------------+
| 1 | 1 | 2013-01-01 |
| 2 | 5 | 2013-01-01 |
| 3 | 2 | 2013-01-01 |
| 2 | 2 | 2013-01-01 |
+-----+---------+------------+
Should give:
+------+--------------+-------+
| Rank | Product | Sales |
+------+--------------+-------+
| 1 | Sun | 7 |
| 2 | Venus | 2 |
| 3 | Moon | 1 |
+------+--------------+-------+
However this sales data:
SalesRows:
+-----+---------+------------+
| Pid | No_sold | Sales_date |
+-----+---------+------------+
| 1 | 1 | 2013-01-01 |
| 2 | 5 | 2013-01-01 |
| 3 | 2 | 2013-01-01 |
| 2 | 2 | 2013-01-01 |
| 4 | 1 | 2013-01-01 |
+-----+---------+------------+
Should give:
+------+--------------+-------+
| Rank | Product | Sales |
+------+--------------+-------+
| 1 | Sun | 7 |
| 2 | Venus | 2 |
| 3 | *2 products* | 1 |
+------+--------------+-------+
Any suggestions how to solve this last part?
This query may help you.
SELECT #rownum := #rownum + 1 rownum,
t.*
FROM (SELECT #rownum:=0) r,
(select case when indicator = 1 then Product
else concat( indicator, ' Products') end as Product, sales from (Select *, count(sales) as indicator from (SELECT Product,SUM(No_sold) AS sales FROM SalesRows
JOIN Products ON Products.Pid = SalesRows.Pid
WHERE Sales_date = curdate()
GROUP BY SalesRows.Pid ) a group by sales Order by sales desc) a) t
Try this :
SELECT Product,SUM(No_sold) AS sales FROM SalesRows
LEFT JOIN Products ON Products.Pid = SalesRows.Pid
WHERE Sales_date = '".$today."'
GROUP BY Pid