SQL select the last 3 dates from a table - mysql

I have a table with lots of fields in mysql
I need a query to return (in the same raw!) the top last 3 dates (dates can have large gaps between them)
ie:
2012/01/20
2012/01/18
2012/01/12
2012/01/10
2012/01/04
etc...
Any help will be appreciated
I must get them in the same row!
This is the query I am trying to use with no success:
SELECT a.id, a.thedate, b.id AS id1, b.thedate AS thedate1, c.id AS id2, c.thedate as thedate2
FROM mytable AS a INNER JOIN mytable AS b ON a.id = b.id INNER JOIN mytable AS c ON b.id=c.id
WHERE c.thedate = SELECT MAX(thedate)

EDIT :
SELECT group_concat(date) FROM (SELECT date FROM my_table ORDER BY date DESC LIMIT 3) AS temp

Corrected-
SELECT group_concat(date) FROM ( select date from table_name order by date desc limit 3) as a

SELECT GROUP_CONCAT(a.date )
FROM (
SELECT date
FROM my_table
ORDER BY date DESC
LIMIT 3
) AS a

Related

Rewrite 2 select statements as one JOIN Statement

I've been strugling with a JOIN statement which I can't figure out.
I want to get the latest(newest) entry in two different tables and join the result in the output.
The 2 Select statements look like this and they work as expected but I can't seem to get the right result when I try to rewite them as a JOIN statement.
Please help, Thanks.
SELECT MaxNum
FROM table1
WHERE UserID = 4
ORDER BY Date DESC
LIMIT 1
SELECT MinNum
FROM table2
WHERE UserID = 4
ORDER BY Date DESC
LIMIT 1
I'm not sure that a join necessarily makes sense here. However, you can slightly modify what you currently have to be one query:
SELECT
(SELECT MaxNum FROM table1 WHERE UserID = 4 ORDER BY Date DESC LIMIT 1) AS MaxNum,
(SELECT MinNum FROM table2 WHERE UserID = 4 ORDER BY Date DESC LIMIT 1) AS MinNum
Since each of these queries only returns one row, one dirty trick you can use is to cross join the results:
SELECT MaxNum, MinNum
FROM (SELECT MaxNum
FROM table1
WHERE UserID = 4
ORDER BY Date DESC
LIMIT 1) t
CROSS JOIN (SELECT MinNum
FROM table2
WHERE UserID = 4
ORDER BY Date DESC
LIMIT 1) s
select TOP 1 table1.MaxNum, table2.MinNum
FROM table1 INNER JOIN table2
ON table1.UserID = table2.UserID
WHERE table1.UserID = 4
ORDER BY table1.Date DESC
If you want to display result as one row then use your queries as subqueries in FROM clause.
SELECT *
FROM
(SELECT MaxNum FROM table1 WHERE UserID = 4 ORDER BY `Date` DESC LIMIT 1) AS q1,
(SELECT MinNum FROM table2 WHERE UserID = 4 ORDER BY `Date` DESC LIMIT 1) AS q2;

mysql query that has join and counts

I need help getting the top 5 results and their counts from columns from two different tables in a mysql database joined together.
table1 cols
-------
id, country, timestamp
table2 cols
--------
id, table1_id, reason
The results id like to get are the top 5 countries and their number of times found between two timestamps, and the top 5 reasons and their counts for all the rows used to generate the first count. There is a one to many relationship between table1 and table2. This is stumping me and I appreciate any insight you could give me.
It's not entirely clear what resultset you want to return.
This may be of some help to you:
SELECT t.country
, COUNT(DISTINCT t.id) AS count_table1_rows
, COUNT(r.id) AS count_table2_rows
, COUNT(*) AS count_total_rows
FROM table1 t
LEFT
JOIN table2 r
ON r.table1_id = t.id
WHERE t.timestamp >= NOW() - INTERVAL 7 DAY
AND t.timestamp < NOW()
GROUP BY t.country
ORDER BY COUNT(DISTINCT t.id) DESC
LIMIT 5
That will return a maximum of 5 rows, one row per country, with counts of rows in table1, counts of rows found in table2, and a count of the total rows returned.
The LEFT keyword specifies an "outer" join operation, such that rows from table1 are returned even if there are no matching rows found in table2.
To get the count for each "reason", associated with each country, you could do something like this:
SELECT t.country
, COUNT(DISTINCT t.id) AS count_table1_rows
FROM table1 t
LEFT
JOIN ( SELECT s.country
, r.reason
, COUNT(*) AS cnt_r
FROM table1 s
JOIN table2 r
ON s.table1_id = t.id
WHERE s.timestamp >= NOW() - INTERVAL 7 DAY
AND s.timestamp < NOW()
GROUP
BY s.country
, r.reason
) u
ON u.country = t.country
WHERE t.timestamp >= NOW() - INTERVAL 7 DAY
AND t.timestamp < NOW()
GROUP
BY t.country
, u.reason
ORDER
BY COUNT(DISTINCT t.id) DESC
, t.country DESC
, u.cnt_r DESC
, u.reason DESC
This query doesn't "limit" the rows being returned. It would be possible to modify the query to have only a subset of the rows returned, but that can get complex. And before we muck the complexity of adding "top 5 within top 5" type limits, we want to ensure that the rows returned by a query are a superset of the rows we actually want.
Is this what you want?
select t2.reason, count(*)
from (select t1.country, count(*)
from table1 t1
where timestamp between #STARTTIME and #ENDTIME
group by country
order by count(*) desc
limit 5
) c5 join
table1 t1
on c5.country = t1.country and
t1.timestamp between #STARTTIME and #ENDTIME join
table2 t2
on t2.table1_id = t1.id
group by t2.reason;
The c5 subquery gets the five countries. The other two bring back the data for the final aggregation.

Why do I receive an error at this join tables?

I wrote this:
SELECT DISTINCT CATEGORY FROM T AS T1
CROSS JOIN (SELECT *
FROM T
WHERE T.CATEGORY = T1.CATEGORY
ORDER BY CATEGORY DESC
LIMIT 10)
and I receive this
"Unknown column 'T1.CATEGORY' in 'where clause'".
Why?
Update:
My purpose of this is to get 10 posts of any category.
Because T1 is not visible from within the subquery.
Your JOIN also serves no purpose and/or you probably forgot the JOIN condition.
In JOIN condition should use ON keyword
SELECT DISTINCT CATEGORY FROM T AS T1
CROSS JOIN SELECT * FROM T ON T.CATEGORY = T1.CATEGORY
ORDER BY CATEGORY DESC LIMIT 10;
If you need to get 10 posts of each category you can use a query like this:
SELECT CATEGORY, Post
FROM (
SELECT a.CATEGORY, a.Post, count(*) as rn
FROM #T a
JOIN #T b ON a.CATEGORY = b.CATEGORY AND a.Post >= b.Post
GROUP BY a.CATEGORY, a.Post) dt
WHERE rn < 11;

MySQL left join and select

I have two tables, mytable1 and mytable2. I get results from mytable1 and left join with mytable2.
CREATE TABLE mytable1
( userid int,
type int,
datetime1 DATETIME );
CREATE TABLE mytable2
( userid int,
name varchar(20),
day2 DATE,
time2 TIME );
SELECT x.*, d.name, d.day2, d.time2
FROM ( SELECT * FROM mytable1 WHERE TYPE=1 ORDER BY userid ASC LIMIT 0,50) x
LEFT JOIN mytable2 d
ON x.userid = d.userid
But I need to filter the results, so I will get only results if "mytable2.day2 mytable2.time2" is bigger than 2 days ago. For example let datetime be "2014.03.27 21:00:00". I will get results if mytable2 record is newer than "2014.03.27 21:00:00"
You can check sql fiddle here inital: http://sqlfiddle.com/#!2/a5364/2
My tryout: http://sqlfiddle.com/#!2/a5364/5
Here is what the query will look like :-
select x.*, d.name, d.day2, d.time2
from ( SELECT * FROM mytable1 WHERE type=1 ORDER BY userid ASC LIMIT 0,50) x
left join mytable2 d
on x.userid = d.userid
where ( convert(CONCAT(d.day2,' ',d.time2),datetime) >= SUBDATE(curdate(),INTERVAL 2 DAY))
Use convert() to get the datetime and then use subdate() to find the date before 2 days.
Verify it on the SQL Fiddle you provided.
The question is: if there are no records at all in mytable2 that match a record in mytable1, do you still want to see the mytable1 record? If so, move the condition to the on clause:
select x.*, d.name, d.day2, d.time2
from (SELECT *
FROM mytable1
WHERE type = 1
ORDER BY userid ASC
LIMIT 0, 50
) x left join
mytable2 d
on x.userid = d.userid and
(d.day2 + d.time2) >= DATE_SUB(NOW(), INTERVAL 2 DAY);
Otherwise, you can change the join to an inner join:
select x.*, d.name, d.day2, d.time2
from (SELECT *
FROM mytable1
WHERE type = 1
ORDER BY userid ASC
LIMIT 0, 50
) x join
mytable2 d
on x.userid = d.userid
where (d.day2 + d.time2) >= DATE_SUB(NOW(), INTERVAL 2 DAY);

Select 5th highest Value without using LIMIT

I am new to SQL and I want to fetch 5th highest value without using LIMIT. Here is the code I am trying but it is not working properly. It is showing the 5th lowest value instead of 5th highest value.
SELECT a . * FROM user AS a
WHERE 5 =
(SELECT count( DISTINCT b.id ) FROM user AS b WHERE b.id >= a.id ORDER BY a.id DESC)
Can anyone help me with this?
You could also do:
SET #nth := 5;
SELECT
a.*
FROM jos_modules AS a
WHERE #nth = (
SELECT
COUNT(b.id)
FROM user AS b
WHERE
a.id >= b.id
);
Try this
SELECT a . *
FROM user AS a
WHERE 5 = (
SELECT count( DISTINCT b.id )
FROM user AS b
WHERE a.id >= b.id ORDER BY a.id )
select * from (
select a.* , row_number() over (order by id asc) as RANK
from a ) where RANK=5 ;
If you are using a Teradata DB , you can use qualify statement :
select * from a
qualify row_number () over(order by id asc)=5;