MySQL querying date range - php

Here's my database (free rooms in a hotel, simplified)
rooms_available:
id date_available room_id
================================
1 2013-12-19 2
2 2013-12-20 2
3 2013-12-21 2
4 2013-12-22 2
5 2013-12-23 2
6 2013-12-25 3
rooms:
id name minimal_range
================================
2 Apartment A 5
3 Apartment B 1
I want to query all rooms which are available between 2013-12-20 and 2013-12-22
My query is like:
select *
from rooms_available
where (date='2013-12-20' OR date='2013-12-21' OR date='2013-12-22')
My questions:
is there a more comfortable way? when the date range will be like 2 weeks, the query will also be very long (which will take much longer for querying)
would it be possible to consider minimum ranges - for example: room_id 2 is only available for at least 5 nights (see table "rooms") -> so above query should return no records
Thanks

date >= '2013-12-20' and date <= '2013-12-22'

SELECT * FROM rooms_available WHERE `date_available` BETWEEN "2013-12-20 " AND "2012-03-31"

I didn't test this but it should point you in the right direction especially for the second part of your question about minimal range.
SELECT t1.id as id, t1.date_available as date_available, t1.room_id
FROM rooms_availble as t1 JOIN rooms as t2 on t1.room_id = t2.id
WHERE t1.date_available BETWEEN DATE('2013-12-20') AND DATE('2012-03-31') AND
t2.minimal_range <= datediff('2013-12-22', '2012-12-20');
The mysql datediff function will return the number of days between two dates then you can just compare it with the minimal_range from the rooms join table. Also you might consider binding the start and end dates to variables so that you only have to write each date once.

Related

Mysql UNION ALL to count multiple columns BUT also insert date column

Hi Guys I have a question. I am still learning and am trying to get some date out. Beneath is the table. It has hundreds of lines, but for example:
FormNR
Datum
XX1
XX2
XX3
0001
2022-09-08
4
23
7
0002
2022-09-10
8
5
0
The table name is 'forms'. Now what I need to do is to count XX1+XX2+XX3 (for a year rapport). Then I have a 'date from and to' selection box on my page. So the question would be:
What instanties have been used between a certain date in total but so that you can see a a total per Instantie (each number is a different instantie).
So for example...Between the 1st of January and the 1st of June a list of all XX numbers ( there are 36 ) with there total behind it
What I have is the following. Is works great and shows all XX's in a nice table but for the entire table, not per date. As soon as i want to add the 'between $date_from AND $date_to' it fails.
<?php
$sql_rg_total="SELECT forms.Datum, x.f1,Count(x.f1)
FROM
(SELECT XX1 As F1 FROM forms
UNION ALL
SELECT XX2 As F1 FROM forms
UNION ALL
SELECT XX3 As F1 FROM forms) x
WHERE x.f1 = '$subcat_id'
GROUP BY x.f1";
$resultvv=mysqli_query($conn, $sql_rg_total);
if (mysqli_num_rows($resultvv) > 0) {
while ($rowvv = mysqli_fetch_assoc($resultvv)) {
$subnr = $rowvv['Count(x.f1)'];
echo $subnr;
}
}
?>
By the way $subcat_id is from another table which connects the number to a name.
I have tried to write it as clear as I could. I know it's a bit thought haha. Thanks anyway for any input. Really stuck.
This query should do it:
SELECT SUM(x.c) AS c
FROM (
SELECT ((XX1 = '$subcat_id') + (XX2 = '$subcat_id') + (XX3 = '$subcat_id')) AS c
FROM forms
WHERE Datum BETWEEN '$date_from' AND '$date_to'
) x
The value of a boolean condition is 1 when it's true, 0 when it's false. So XX1 = '$subcat_id' + XX2 = '$subcat_id' + XX3 = '$subcat_id' adds up the number of columns that match in a row, then SUM(c) totals them in the entire table.
You don't need GROUP BY, since it's the same column that you're filtering in the WHERE condition (and now in the SELECT expression). And this moves the date condition into the subquery.

How to get count,type,date with distinct user_id in single query

I created a table in MySQL. It consists of data like this:
Table user_pack:
id type from to user_id current_plan created_ at
1 trail 01-01-2016 05-01-2016 1 0 01-01-2016
2 free 06-01-2016 10-01-2016 1 0 06-01-2016
3 main 11-01-2016 20-01-2016 1 1 11-01-2016
4 main 21-01-2016 29-02-2016 1 1 21-01-2016
5 trail 01-01-2016 29-02-2016 2 1 01-01-2016
6 trail 01-01-2016 05-01-2016 3 0 01-01-2016
7 free 06-01-2016 29-02-2016 3 1 06-01-2016
user_id= 1 =>first register for type=trail it started from = 01-01-2016 to=05-01-2016.in that time current_plan=1 after expired current_plan=0.
=>second register for type=free it started from = 06-01-2016 to=10-01-2016 in that time current_plan=1 after expired current_plan=0.
=>third register for type=main it started from = 11-01-2016 to=20-01-2016 in that time current_plan=1 after expired current_plan=1 only
=>fourth register for type=main it started from = 21-01-2016 29-02-2016 and now it in activation current plan=1.
When I search in between two dates 01-01-2016 and 21-01-2016 with respect to created_at and current plan must be 1 and today date must be in between from and to date in table.
I want the output result in this way:
array0=>['trail count'=>1,'free count'=>0,'main count'=>0,'date'=>01-01-2016]
array1=>['trail count'=>0,'free count'=>1,'main count'=>0,'date'=>06-01-2016]
array2=>['trail count'=>0,'free count'=>0,'main count'=>0,'date'=>11-01-2016]
array3=>['trail count'=>0,'free count'=>0,'main count'=>1,'date'=>21-01-2016]
To be able to perform this type of query you should consider to split up your table into 3 different tables:
pack_type:
id
type
pack_event:
id
pack_type_id
from
to
pack_registration:
id
pack_event_id
user_id
current_plan
created_at
This structure will prevent redundancy and also enables you to make sophisticated queries. It is also important to use date columns for from, to and created_at.
With this table structure you will be able to query all user registrations for the given time period and current_plan=1 with the following query:
select
count(pe.id) as register_count,
pt.type
from
pack_registration pr
cross join pack_type pt
left join pack_event pe on pr.pack_event_id = pe.id and pe.pack_type_id = pt.id
where
pr.current_plan = 1 and
pr.user_id = 1 and
pr.created_at between '2016-01-01' and '2016-01-31'
group by
pt.type

How to filter the total sales record every month using sql query?

I am generating a sales report and I am having a hard time with the query. I am not really good in query. I hope you can help me with this. Ok here it is.
I have a sales table. And the structure is like this
EX:
product_id name date_purchased
1 apple 2014-01-03 12:00:59
2 orange 2014-01-05 10:12:20
3 banana 2014-02-01 09:25:01
4 mango 2014-02-20 18:13:25
5 stawberry 2014-02-28 13:14:30
6 jackfruit 2014-05-26 08:16:31
7 grapes 2014-11-03 09:25:21
8 guava 2014-12-25 10:15:45
Now I want to count the item purchased every month
My output result should be like this
2,3,0,0,1,0,0,0,0,0,1,1
2 represents Jan,
3 represents Feb,
etc...
My query looks like this but I know it is wrong.. :(
SELECT COUNT(product_id) FROM sales_table GROUP BY date_purchased
How can I do that using a query? Or should I make a PHP function for this?
try like this :
SELECT year(date_purchased), month(date_purchased), COUNT(product_id)
FROM sales_table
GROUP BY concat(year(date_purchased), month(date_purchased))
I think you can retrieve the dates and use PHP as it is pretty straight forward.
Once you have a date lets say for example,
$date_str = "2014-01-03 12:00:59"; //let's say you fetch this from DB
$month = date('m',strtotime($date_str)); //this will automatically output 1
You mentioned, 2 represents Jan, 3 represents Feb etc, so you can just add 1 to $month and you have what you need.
Hope it should work
SELECT COUNT(product_id) FROM sales_table GROUP BY DATENAME(month, date_purchased)
The SQL query is enough.
You have to use group by.
But first make a month column for your table.
create function byMonth(#myDate datetime)
returns datetime
as
begin
declare #newDate
set #newDate = year(#myDate) + '/' + month(#myDate) + '/1 00:00:00'
return #newDate
end
go
and use this in your query:
Select Count(*),byMonth(date_puchased) as x
from myTable
where ...
group by x
having ...
this should work for you.
More elaborated solutions
To get Month - wise
SELECT COUNT(id) FROM testrec GROUP BY DATE_FORMAT(pur,'%M');
Get all details
SELECT COUNT(product_id),`name` , date_purchased, DATE_FORMAT(date_purchased,'%M') FROM sales_table GROUP BY DATE_FORMAT(pur,'%M');

how to split multiple columns into multiple rows in sql (for school time table)

My table for school time table in mysql is like this:
--------------------------------------------------------------------------------------------
SectionID|P1|P2|P3|P4|P5|P6|P7|P8|P9|P10|P11|P12|P13|P14|P15|P16|P17|P18|P19|P20........P35|
--------------------------------------------------------------------------------------------
per day 7 periods so 5 working days 35 periods in that table..
I want to display the data in daily time table view like
-------------------------------------------------------------------
|P1 |P2 |P3 |P4 |P5 |P6 |P7 |
-------------------------------------------------------------------
p1data p2data p3data p4data p5data p6data p7data
p8data p9data p10data p11data p12data p13data p14data
p15data p16data p17data p18data p19data p20data p21data
..........................................................upto p35data
for 5 days using JQUERY,PHP,MYSQL
Note: don't display the column name for P8 to P35 in that display table.. day column while displaying time table is our wish..
select
if(p.period=1, t.P1, if (p.period=2, t.P8, if (p.period=3, t.P15, if (p.period=4, t.P22, t.P29)))) as p1,
if(p.period=1, t.P2, if (p.period=2, t.P9, if (p.period=3, t.P16, if (p.period=4, t.P23, t.P30)))) as p2,
...
from the_table t,
(select 1 as period
union all
select 2 as period
union all
select 3 as period
union all
select 4 as period
union all
select 5 as period) p
Join artificial table and place columns depending on period
Instead of the if() you can use CASE/WHEN
Select Value , Substring(FullName, 1,Charindex(',', p1)-1) as period,
Substring(p1, Charindex(',', p1)+1, LEN(p1)) as period
from Table1

I want the last row of all players in a specific month+year

Here is a simplified version of my sql table of 2 months (ORDERED BY DATE):
player_id |
date |
score
1 2011-05-25
1200
2 2011-05-25
3400
3 2011-05-26
3200
4 2011-05-26
4400
1 2011-05-28
1000
2 2011-05-28
2000
3 2011-05-29
3000
4 2011-05-29
4000
1 2011-06-24
1300
2 2011-06-24
2500
3 2011-06-24
5000
4 2011-06-24
3000
Basically, I want a query that shows the last score of all players in a specific month/specific year.
Example:
If I want the final scores of all players in the month 05, te result
would be:
1 2011-05-28 1000
2 2011-05-28 2000
3 2011-05-29 3000
4 2011-05-29 4000
My sql query so far:
SELECT m1.* FROM table m1
LEFT JOIN table m2 ON (m1.player_id = m2.player_id AND m1.date < m2.date)
WHERE m2.date IS NULL
AND month(m1.date) = 05
AND year(m1.date) = 2011
ORDER BY score DESC);
This doesn't seem to show all players, only players that didn't play in the months after 05. Where do I add the date select?
**EDIT
John Nestoriak's answer bellow did the trick for me :)
I think he's referring to the technique shown here: Retrieving the last record in each group
With the additional constraint of he doesn't want the last record but the last record in a given month.
Oddly enough you have to give that additional constraint twice, once in the join condition and again to filter the results. This should do it for you.
SELECT m1.* FROM table m1
LEFT JOIN table m2 ON
(m1.player_id = m2.player_id AND m1.date < m2.date
AND m2.date < '2011-06-01')
WHERE m2.date IS NULL AND month(m1.date) = 5 AND year(m1.date) = 2011
Assuming that the (player_id, date) combination in Unique:
SELECT
t.*
FROM
TableX AS t
JOIN
( SELECT
player_id
, MAX(date) AS maxDate
FROM
TableX
WHERE
date BETWEEN '2011-05-01'
AND LAST_DAY('2011-05-01')
GROUP BY
player_id
) AS tg
ON
(tg.player_id, tg.maxDate) = (t.player_id, t.date)
ORDER BY
t.score DESC

Categories