Rewrite 2 select statements as one JOIN Statement - mysql

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;

Related

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;

Sub-query with count(*)

How to get the data that is failed that associate with left(number,7) from sub query count(*) data?
For example I did this:
SELECT * FROM table1 WHERE outcome = 'Fail' AND left(number,7) =
(SELECT count(*) as total, left(number,7) as prefix
FROM table1 where outcome like '%Passed%'
group by prefix order by total desc limit 250)
This wont work because there are two fields in the sub-query.. so how to get around that?
You can use JOIN instead of subquery:
SELECT t1.*, t2.total, ...
FROM table1 AS t1
INNER JOIN
(
SELECT count(*) as total, left(number,7) as prefix
FROM table1
where outcome like '%Passed%' AND outcome = 'Fail'
group by prefix
order by total desc limit 250
) AS t2 ON t2.prefix = left(t1.number,7)
Try this query
SELECT *
FROM
table1 a
INNER JOIN
(SELECT
count(*) as total,
left(number,7) as prefix
FROM
table1
where
outcome like '%Passed%'
group by
prefix
order by
total desc limit 250)b
ON
a.outcome = 'Fail' AND
left(number,7) = b.prefix

Unique result set with inner join query

SELECT
*
FROM `catalog_webdesign_products` t
INNER JOIN tbl_member_registration t1 ont.userid=t1.fld_loginid
WHERE 1
AND t1.fld_member_category_level<9
AND t.product_img IS NOT NULL
ORDER BY RAND() LIMIT 5
In this query , I need rows with unique userid. I had tried 'group by userid' also but then product_img with null value is coming in result set.
yes you can use GROUP BY userid. but your query looks wrong here
INNER JOIN tbl_member_registration t1 on t.userid=t1.fld_loginid
^------------------------space here
try this
SELECT
*
FROM `catalog_webdesign_products` t
INNER JOIN tbl_member_registration t1 on t.userid=t1.fld_loginid
WHERE t1.fld_member_category_level<9
AND t.product_img IS NOT NULL
group by userid
ORDER BY RAND() LIMIT 5
edit:
SELECT
*
FROM (select * from `catalog_webdesign_products` where product_img IS NOT NULL) t
INNER JOIN tbl_member_registration t1 on t.userid=t1.fld_loginid
WHERE t1.fld_member_category_level<9
group by t.userid
ORDER BY RAND() LIMIT 5
For better performance you should move the condition for t1 into join statement. You problem could be the wrong JOIN condition. Try LEFT JOIN instead of INNER JOIN.
More about joins: http://www.w3schools.com/sql/sql_join.asp
SELECT *
FROM `catalog_webdesign_products` t
LEFT JOIN tbl_member_registration t1
ON (t.userid = t1.fld_loginid AND t1.fld_member_category_level < 9)
WHERE t.product_img IS NOT NULL
GROUP BY t.userid
ORDER BY RAND() LIMIT 5

SQL select the last 3 dates from a table

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