MySQL select all last added query - mysql

Im trying to select all the items that are recently added.
I have to find what is the last added exam (sometimes more that one as shown below)
Here is an example of the DB.
id name start_date end_date duration
4 Exam August 2011 24.8.2011 0000-00-00 20
3 Exam July 2011 28.7.2011 0000-00-00 20
5 Exam August 2011 24.8.2011 0000-00-00 20
6 Exam August 2011 24.8.2011 0000-00-00 20
25 Exam September 2011 26.9.2011 07.10.2011 20
26 Exam September 2011 26.9.2011 07.10.2011 20
27 Exam September 2011 26.9.2011 07.10.2011 20
And here is the query that im using, my question is is there a better way to do it? Some optimization?
SELECT * FROM me_tests WHERE name = (
SELECT name FROM me_tests ORDER BY start_date DESC LIMIT 1
)
The second query will find the name of the last added (same as start date) one, will pass it to the first select and will select all the other tests based on the name.

SELECT * FROM me_tests ORDER BY start_date DESC LIMIT 1
Or -
SELECT * FROM me_tests
WHERE start_date =
(SELECT MAX(start_date) FROM me_tests);

What if the last added items were added at the same time but have different names?
In that case I would think you would want a query like this.
SELECT
*
FROM me_tests
WHERE start_date = (SELECT
start_date
FROM me_tests
ORDER BY start_date DESC LIMIT 1)

I would use
SELECT * FROM me_tests ORDER BY start_date DESC LIMIT 1
... except using * is bad, so you should name all the columns you want to retrieve.

Related

Limit Table By Latest/Highest Date

I am trying to select from a table like this below and limit it by the latest date.
record_date
Name
Age
2021-05-19
John
21
2021-05-19
Smith
25
2021-05-19
Mary
20
2021-05-20
Ann
26
2021-05-20
Jane
23
I tried doing
SELECT * FROM table WHERE DATE(record_date) BETWEEN MAX(DATE(record_date)) AND MAX(DATE(record_date))
The above code does not work, but this is what I am trying to acheive below:
record_date
Name
Age
2021-05-20
Ann
26
2021-05-20
Jane
23
I don't want to hard-code the date into the statement, because records come in everyday, so it has to be able to select the latest date and limit only that. Thanks!
Something like:
select * from table where record_date = (select max(record_date) from table)
One more query using JOIN
select t.*
from t
join (select max(record_date) max_date from t) max_date_t on record_date = max_date;
MySQL fiddle

Select nearest date in the interval

I'm trying to select rows in which 3+ posts is in the interval 14 days.
For example:
User | id_post | date
1 | 12 | 2018-01-01
1 | 13 | 2018-01-05
1 | 14 | 2018-01-21
1 | 15 | 2018-01-27
1 | 16 | 2018-01-29
2 | 17 | 2018-01-01
2 | 18 | 2018-01-20
2 | 19 | 2018-02-17
2 | 20 | 2018-03-07
2 | 21 | 2018-04-29
User = OwnerUserId
date = CreationDate
In this case I need to return just User 1 because he has posts which are in 14 days.
Please, help me how I can get it. Thank you
Update: A user should have posts which were published in the interval of 14 days. It can be more, for example if the last day is in 2019 but in 2018 there was 3posts published within 14 days - it's ok
now i have (data get from data.stackexchange stackoverflow) and tried to apply
select OwnerUserId from Posts as p
where OwnerUserId in (select Users.id from Users WHERE YEAR (Users.CreationDate) >= 2017)
AND YEAR (p.CreationDate) >= 2018
AND p.Tags like '%sql%'
join (select OwnerUserId, CreationDate as startdate, dateadd(day,14,CreationDate) as enddate
from Posts) as r
on p.OwnerUserId = r.OwnerUserId and p.CreationDate between r.startdate and r.enddate
group by p.OwnerUserId, CreationDate
having count(*) >= 3
but it replies
Incorrect syntax near the keyword 'join'.
Incorrect syntax near the keyword 'as'.
I'm a begginner here and in the sql, so i dont exactly know how to combine my previous 'filtr' and current join with date
I'll not tell you the solution, but give you some pseudo-code and you figure out how to code it in SQL-
a) You should restrict your data for just 14 days.
b) Now, make groupings by User and find the count of records/lines present (for each User).
c) Now, again do a filter check to find users whose count of records is greater than 3.
Now, tell us which SQL keywords will be used for each points above.
I think something like
select p.user_id
from posts p
join (select user_id, xdate start_date, date_add(xdate, interval 14 day) end_date
from posts) r
on p.user_id = r.user_id and p.xdate between r.start_date and r.end_date
group by user_id, start_date
having count(*) >= 3
can help. It may not be the best possible solution, but it works.
Check it on SQL Fiddle
If you just want to select users by id you may try
Select id_post, date from yourtable where user = 2 order by id DESC limit 10;
You should have Colum called id with auto increment so new posts will have higher id so when it's sorted in descending it will start with post with higher id also you should have index on that id colum auto increment and index
If you don't want to use the above method then you will do that with date range like this
$date = gmdate() - (3600*24); 24 is 24 hours past
Select id_post, title from mutable where add_date > 'value of $date'
In both cases you should have index on user id
The second query is what you need but you should get the date from the equation first then apply it to the query
First, I think you mean user 1 not 2.
In MySQL 8+, this is pretty easy. If you want the first such post:
select t.*
from (select t.*,
lead(date, 2) over (partition by user order by date) as next_date2
from t
) t
where next_date2 <= date + interval 14 day;

Check if instances have occurred minimum once, every year in a specific range

In MySQL I'm tasked with a big dataset, with data from 1970 to 2010.
I want to check for consistency: check if each instance occurs minimum one time per year. I took a snippet from 1970-1972 as example to demonstrate my problem.
input:
id year counts
-- ---- ---------
1 1970 1
1 1971 1
2 1970 3
2 1971 8
2 1972 1
3 1970 4
expected:
id 1970-1972
-- ----------
1 no
2 yes
3 no
I though about counting within the date range and then taking those out who had 3 counts: 1970, 1971, 1972. The following query doesn't force the check on each point in the range though.
select id, count(*)
from table1
WHERE (year BETWEEN '1970' AND '1972') AND `no_counts` >= 1
group by id
What to do?
You can use GROUP BY with CASE / inline if.
Using CASE. SQL Fiddle
select id,CASE WHEN COUNT(distinct year) = 3 THEN 'yes'ELSE 'No' END "1970-72"
from abc
WHERE year between 1970 and 1972
GROUP BY id
Using inline IF. SQL Fiddle
select id,IF( COUNT(distinct year) = 3,'yes','No') "1970-72"
from abc
WHERE year between 1970 and 1972
GROUP BY id
You can use a having clause with distinct count:
select `id`
from `table1`
where `year` between '1970' and '1972'
group by id
having count(distinct `year`) = 3
Do you expect this?
select id, count(*)
from table1
WHERE (year BETWEEN '1970' AND '1972')
group by id
having count(distinct year) = 3

MySQL order by IF and sorting dates

In sorting the ORDER BY of dates in MySQL, I'm trying to sort ASC for dates after today, and DESC for dates before today in one go.
I'm doing something similar to:
SELECT * FROM test ORDER BY IF(created >= NOW(), created, 1) ASC, created DESC
This gives me a somewhat desired result:
ID CREATED
8 May, 10 2014 11:15:00+0000
7 May, 03 2014 20:47:00+0000
5 May, 02 2014 14:00:00+0000
4 April, 30 2014 17:41:00+0000
3 April, 30 2014 17:00:00+0000
1 April, 21 2014 03:30:00+0000
6 March, 23 2014 12:00:00+0000
9 May, 20 2014 20:45:00+0000
10 July, 02 2014 20:30:00+0000
2 June, 30 2015 11:16:00+0000
Before today is DESC, after today is ASC. However, I want to see the block of ID's 9,10,2 at the top of the results.
Any thoughts on how to do this is appreciated.
Test Link: http://www.sqlfiddle.com/#!2/4667b/2/0
Add an additional condition to the order by, which is a binary indicator of whether the date is in the past or future:
SELECT *
FROM test
ORDER BY (created >= NOW()) desc,
IF(created >= NOW(), created, NULL) ASC,
created DESC;
how about splitting it up into 2 sql queries and then unioning the results?
(SELECT * FROM test WHERE created >= NOW() ORDER BY created ASC)
UNION
(SELECT * FROM test WHERE created < NOW() ORDER BY created DESC)

Given a table with time periods, query for a list of sum per day

Let's say I have a table that says how many items of something are valid between two dates.
Additionally, there may be multiple such periods.
For example, given a table:
itemtype | count | start | end
A | 10 | 2014-01-01 | 2014-01-10
A | 10 | 2014-01-05 | 2014-01-08
This means that there are 10 items of type A valid 2014-01-01 - 2014-01-10 and additionally, there are 10 valid 2014-01-05 - 2014-01-08.
So for example, the sum of valid items at 2014-01-06 are 20.
How can I query the table to get the sum per day? I would like a result such as
2014-01-01 10
2014-01-02 10
2014-01-03 10
2014-01-04 10
2014-01-05 20
2014-01-06 20
2014-01-07 20
2014-01-08 20
2014-01-09 10
2014-01-10 10
Can this be done with SQL? Either Oracle or MySQL would be fine
The basic syntax you are looking for is as follows:
For my example below I've defined a new table called DateTimePeriods which has a column for StartDate and EndDate both of which are DATE columns.
SELECT
SUM(NumericColumnName)
, DateTimePeriods.StartDate
, DateTimePeriods.EndDate
FROM
TableName
INNER JOIN DateTimePeriods ON TableName.dateColumnName BETWEEN DateTimePeriods.StartDate and DateTimePeriods.EndDate
GROUP BY
DateTimePeriods.StartDate
, DateTimePeriods.EndDate
Obviously the above code won't work on your database but should give you a reasonable place to start. You should look into GROUP BY and Aggregate Functions. I'm also not certain of how universal BETWEEN is for each database type, but you could do it using other comparisons such as <= and >=.
There are several ways to go about this. First, you need a list of dense dates to query. Using a row generator statement can provide that:
select date '2014-01-01' + level -1 d
from dual
connect by level <= 15;
Then for each date, select the sum of inventory:
with
sample_data as
(select 'A' itemtype, 10 item_count, date '2014-01-01' start_date, date '2014-01-10' end_date from dual union all
select 'A', 10, date '2014-01-05', date '2014-01-08' from dual),
periods as (select date '2014-01-01' + level -1 d from dual connect by level <= 15)
select
periods.d,
(select sum(item_count) from sample_data where periods.d between start_date and end_date) available
from periods
where periods.d = date '2014-01-06';
You would need to dynamically set the number of date rows to generate.
If you only needed a single row, then a query like this would work:
with
sample_data as
(select 'A' itemtype, 10 item_count, date '2014-01-01' start_date, date '2014-01-10' end_date from dual union all
select 'A', 10, date '2014-01-05', date '2014-01-08' from dual)
select sum(item_count)
from sample_data
where date '2014-01-06' between start_date and end_date;