SQL: Get unique data between two dates - php

Hi I am using a mysql table "student" which has 4 columns:
Id Name Date StudentId
1 John 2010-01-15 3
2 Matt 2010-01-10 5
3 Jane 2010-02-10 8
4 John 2010-02-11 3
5 Matt 2010-02-11 5
6 Jane 2010-02-11 8
I want to fetch only new entries in the table between 2010-02-10 and 2010-02-12. If a student had a previous entry in the table then the query should not return that value. So in the above case the query should only return both entries of Jane since John and Matt had an entry each previous to the date specified.
This is what I have but it is not working:
SELECT * FROM student
WHERE date(Date)
between '2010-02-10' and '2010-02-12'
and date(Date)
not between '0000-00-00' and '2015-02-09';

GROUP BY and HAVING is what you are looking for if you want single record per student:
SELECT * FROM student
GROUP BY Name
HAVING DATE(Date) BETWEEN '2010-02-10' AND '2010-02-12';
Or I would use subquery if you want all the records:
SELECT * FROM student
WHERE DATE(Date) BETWEEN '2010-02-10' AND '2010-02-12'
AND Name NOT IN
(SELECT DISTINCT Name FROM student WHERE DATE(Date) < '2010-02-10');
How it works:
the subquery selects all the names that have records prior to the date range, i.e. the ones you don't want in your result. It produces set like ('John', 'Matt'). The main query then selects all the records in the given date range where Name NOT IN ('John', 'Matt').

Related

calculate date difference between consecutive rows in mysql

I have a TABLE in mysql with Columns:
id, created_time, name
Every row has id and the date time when it has been created . For example below:
id created_on name
1 2020-12-03 13:15:09 john
2 2020-11-08 14:11:19 john
3 2020-10-06 14:11:19 john
4 2020-09-12 14:11:19 john
Want to show result in which the difference between 2 rows is greater than 30 days
Expected Output : -
id created_on name
2 2020-11-08 14:11:19 john
4 2020-09-12 14:11:19 john
I have tried with below query but failed as it shows all the data.
SELECT id
, name
FROM
( SELECT MIN(created_on) start_time
, id
, name
FROM table1
WHERE name = 'john'
GROUP
BY id
) start_action
JOIN
( SELECT MAX(created_on) close_time
, id
, name
FROM table1
WHERE name = 'john'
GROUP
BY id
) close_action
USING (id,name)
WHERE name = 'john'
I am using Mysql 5.6 version Request to please help
You could use LEAD here for a MySQL 8+ solution:
WITH cte AS (
SELECT *, LEAD(created_time) OVER (ORDER BY id) lead_created_time,
LAG(created_time) OVER (ORDER BY id) lag_created_time
FROM yourTable
)
SELECT id, created_time
FROM cte
WHERE ABS(DATEDIFF(lead_created_time, created_time)) > 30 OR
ABS(DATEDIFF(lag_created_time, created_time)) > 30;
Demo

How to select specific rows from MYSQL using PHP?

I have a chat app and I'm using PHP to get the data from MYSQL. I don't know how to word this the best way so I'm going to illustrate it the best way I can. Below is the an example the database setup.
DATABASE
ID MESSAGE DATETIME
------------------------------------------
1 Hello1. 2019-04-23 23:04:31
1 Hello2. 2019-03-23 10:04:31
1 Hello3. 2019-04-26 22:04:31
1 Hello4. 2019-04-23 13:01:10
2 Hello5. 2019-04-09 23:04:31
2 Hello6. 2019-04-23 23:04:31
2 Hello7. 2019-04-12 23:04:12
2 Hello8. 2019-04-11 20:04:31
3 Hello9. 2019-05-18 19:04:29
3 Hello10. 2019-02-22 23:04:31
3 Hello11. 2019-03-25 23:04:30
4 Hello12. 2019-04-23 15:04:31
4 Hello13. 2019-04-10 23:04:31
5 Hello14. 2019-01-14 23:04:31
SHOULD SELECT
ID MESSAGE DATETIME
------------------------------------------
1 Hello3. 2019-04-26 22:04:31
2 Hello6. 2019-04-23 23:04:31
3 Hello9. 2019-05-18 19:04:29
4 Hello12. 2019-04-23 15:04:31
5 Hello14. 2019-01-14 23:04:31
What I am trying to do is select the newest ID once for each different ID. So for ID 1 I would only be selecting the one with the newest DATETIME and so on and so forth.
mysql_query("SELECT * FROM messages WHERE ____?____ ORDER BY __?__");
So in this case there should only be 5 results. One of each id with the newest dateline. Any help would be greatly appreciated. Thanks.
You want the MAX(date) value, but one per ID. Because you also want the message, which does not appear in the GROUP BY clause, you should run a join on the table towards itself.
In the joined table, you get the maximum date and the ID, grouped by the ID - this gives you the highest date for each ID. Join that on your table on the ID and date, which allows you to get other columns that do not exist in the GROUP BY (as this GROUP BY is in the joined table, you don't need it in the main table).
SELECT m.id, m.message, m.date
FROM messages m
JOIN (
SELECT id, MAX(date) AS date
FROM foo
GROUP BY id
) AS t
ON m.id=t.id AND m.date=t.date
SQL fiddle shows the live result http://sqlfiddle.com/#!9/c70c3/7
You could try sorting them in a subquery before grouping by the ID as follows:
SELECT * FROM (SELECT * FROM messages ORDER BY DATETIME DESC) AS sortedMessages GROUP BY ID;
OR
mysql_query("SELECT * FROM (SELECT * FROM messages ORDER BY DATETIME DESC) AS sortedMessages GROUP BY ID;");
Or you could build a second table with conversations , that could have a subject and the latest message in the row , and then you would just return that full table, when opening the conversation you would pull the indivual messages from the messages table based on the conversationID

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

MySQL querying date range

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.

Selecting a distinct value and the sum of times it shows up in a column

I have an existing table with millions of entries (growing) that consists of:
userid|name|etc...
1 frank ...
1 frank ...
2 joe ...
5 sam ...
1 franky ...
What I need to do is return a table of:
place|name|total
1 franky 3
2 sam 1
3 joe 1
Where total is the SUM(userid = the distinct userid).
Currently I'm doing a query to SELECT DISTINCT userid from table and then foreach returned value in php, I'm doing another query to return the name and sum(userid = userid).
As you can assume, this is very taxing and takes a long time now with all of the values. Is there any way to speed this up by doing 1 query?
i think you need
SELECT #a:=#a+1 AS `place`, name, COUNT(userid) AS `total`
FROM `your_table`, (SELECT #a:= 0) AS a
GROUP BY userid
SELECT userid, COUNT(*)
FROM some_table
GROUP BY userid

Categories