I need to join two tables, which are:
TABLE 1
t1_id | t1_text | t1_date
TABLE 2
t2_id | t2_text | t2_date | t1_id
What i want to get:
t1_text | t1_date | t2_text | t2_date
table has to show most recent, unique, t1 rows, together with their linked t2_text and its t2_date
This is what ive got so far:
SELECT `table_1`.`t1_text` AS 'Text', `table_1`.`t1_date` AS 't1_date', `table_2`.`t2_text` AS 't2_Text', `table_2`.`t2_date` AS 'Date'
FROM `table_1`
LEFT JOIN `table_2` ON `table_1`.`t1_id`=`table_2`.`t1_id`
ORDER BY `table_1`.`t1_date` DESC
LIMIT 10
Its close, but no cigar. I still get the same t1 rows to show up more than once
I am not sure I understand clearly what is your desired output. Try the following:
SELECT news.text AS 'News', news.date AS 'Publish date',
comments.text AS 'Most Recent Comment', comments.date AS 'Comment Date'
FROM news
JOIN (
SELECT text, MAX(newsId) as newsId, date
FROM comments
GROUP BY newsId
)comments ON news.newsId=comments.newsId
WHERE comments.text IS NOT NULL
ORDER BY news.date DESC LIMIT 10
With clarification regarding the uniqueness of the id fields:
select t1.t1_id, t1.t1_date, t1.t1_text, t2.t2_id, t2.t2_date, t2.t2_text
from table_1 t1
inner join (SELECT t1_id, max(t1_date) as date from table_1) t1m
on t1.t1_id = t1m.t1_id and t1.t1_date = t1m.date
inner join table_2 t2
on t1.t1_id = t2.t1_id
inner join (SELECT t2_id, max(t2_date) as date from table_2) t2m
on t2.t2_id = t2m.t2_id and t2.t2_date = t2m.date;
In this query the inline tables select the ids with the max date, which are then joined to the original table to get the remaining fields.
There still may be duplicate t1_id's however if the combination of t1_id and t1_date is not unique. But in that case I don't think that duplication should be hidden, but rather adressed.
Original answer:
You need to use an inner join rather than a left join.
SELECT `table_1`.`t1_text` AS 'Text', `table_1`.`t1_date` AS 't1_date', `table_2`.`t2_text` AS 't2_Text', `table_2`.`t2_date` AS 'Date'
FROM `table_1`
INNER JOIN `table_2`
ON `table_1`.`t1_id`=`table_2`.`t1_id`
ORDER BY `table_1`.`t1_date` DESC LIMIT 10
Also, some of your quote characters are not consistent, different databases may require different quote characters to delimit names, but the mix might give you problems.
Related
I'm new to MySQL, and I'd like some help in setting up a MySQL query to pull some data from a few tables (~100,000 rows) in a particular output format.
This problem involves three SQL tables:
allusers : This one contains user information. The columns of interest are userid and vip
table1 and table2 contain data, but they also have a userid column, which matches the userid column in allusers.
What I'd like to do:
I'd like to create a query which searches through allusers, finds the userid of those that are VIP, and then count the number of records in each of table1 and table2 grouped by the userid. So, my desired output is:
userid | Count in Table1 | Count in Table2
1 | 5 | 21
5 | 16 | 31
8 | 21 | 12
What I've done so far:
I've created this statement:
SELECT userid, count(1)
FROM table1
WHERE userid IN (SELECT userid FROM allusers WHERE vip IS NOT NULL)
GROUP BY userid
This gets me close to what I want. But now, I want to add another column with the respective counts from table2
I also tried using joins like this:
select A.userid, count(T1.userid), count(T2.userid) from allusers A
left join table1 T1 on T1.userid = A.userid
left join table2 T2 on T2.userid = A.userid
where A.vip is not null
group by A.userid
However, this query took a very long time and I had to kill the query. I'm assuming this is because using Joins for such large tables is very inefficient.
Similar Questions
This one is looking for a similar result as I am, but doesn't need nearly as much filtering with subqueries
This one sums up the counts across tables, while I need the counts separated into columns
Could someone help me set up the query to generate the data I need?
Thanks!
You need to pre-aggregate first, then join, otherwise the results will not be what you expect if a user has several rows in both table1 and table2. Besides, pre-aggregation is usually more efficient than outer aggregation in a situation such as yours.
Consider:
select a.userid, t1.cnt cnt1, t2.cnt cnt2
from allusers a
left join (select userid, count(*) cnt from table1 group by userid) t1
on t1.userid = a.userid
left join (select userid, count(*) cnt from table2 group by userid) t2
on t2.userid = a.userid
where a.vip is not null
This is a case where I would recommend correlated subqueries:
select a.userid,
(select count(*) from table1 t1 where t1.userid = a.userid) as cnt1,
(select count(*) from table2 t2 where t2.userid = a.userid) as cnt2
from allusers a
where a.vip is not null;
The reason that I recommend this approach is because you are filtering the alllusers table. That means that the pre-aggregation approach may be doing additional, unnecessary work.
Table 1:
user score
------------
A 1
B 2
Table 2:
user comment time
----------------------------
A good <timestamp 1>
A bad <timestamp 2>
B average <timestamp 3>
I want to join these two tables such that I get the below:
user score comment
-------------------------
A 1 good
B 2 average
As you can see I'll need to join the second table's comment based on the timestamp (the most recent timestamp). I tried
SELECT st.user as user,st.score,
case when v.comment is null then 'NA' else v.comment end as comment
FROM tale1
left JOIN (select distinct user,comment,max(time) from table2) v ON st.user=v.user
but this doesnt work.
You can join with a correlated subquery that filters on the latest timestamp:
select
t1.*,
t2.comment
from table1 t1
left join table2 t2
on t2.user = t1.user
and t2.time = (
select max(t22.time)
from table2 t22
where t21.user = t1.user
)
Side note: I am unsure that you do need a left join here (your sample data does not demonstrate that).
You only want one column from table2 so I recommend a correlated subquery:
select t1.*,
(select t2.comment
from table2 t2
where t2.user = t1.user
order by t2.time desc
limit 1
) as comment
from table1 t1;
This query will make optimal use of an index on table2(user, time desc, comment) -- alas, though, I think the desc is ignored in MySQL.
I have two tables that store comments from two different users
Table1
id_table1 | comment | id_user | id_post
Table2
id_table2 | comment | id_someOtherUser | id_post
I would really like to make only one table out of this two because comments are posted on the same post, but i can't because i have two different id's for two different kind of users.
My question is how can i list all posts DESC by number of comments combined from two tables?
If i do something like
SELECT P.*, count(*) as count from Table1 AS T1
LEFT JOIN post AS P ON T1.id_post = P.id_post GROUP BY P.id_post ORDER BY count DESC
Then i have posts for table1, same can be done for table2, but how can i combine comments from both tables for the same post?
I would use UNION ALL to combine the two comment tables in a common format, then do the JOIN:
SELECT P.*, TC.count
FROM (
SELECT Ts.id_post, count(*) AS count
FROM (
SELECT id_post FROM Table1
UNION ALL
SELECT id_post FROM Table2
) AS Ts
GROUP BY Ts.id_post
) AS TC
LEFT JOIN post AS P ON TC.id_post = P.id_post
GROUP BY P.id_post
ORDER BY TC.count DESC
One way to solve this is to do separate counts on each table, then do a full outer join, and take the sum of each of the counts:
SELECT id_post, (count1 + count2) AS total_count FROM
(SELECT id_post, count(*) as count1 from Table1 AS T1
FULL OUTER JOIN
(SELECT id_post, count(*) as count2 from Table2 AS T2)
USING(id_post))
ORDER BY total_count DESC
I have 3 tables and want to join all in one query to show latest 10 entries by datetime.
t1: id, username
t2: id, id_t1, med_id, ga_id, au_id, re_id, text, datetime
t3: id, id_t1, pro_id, au_id, re_id, text, datetime
First I saw it would be easy with simple left join and where id, but i got double results. Then i tried inner and outer join, also group by, but the result was bad.
So my question is how can i join all without double results of the last 10 of t2 and t3?
Hard to tell what exactly you are trying to acheive, but here is a clue how it could be complemented.
SELECT TOP 10 DISTINCT T1.*
FROM T1
INNER JOIN T2 ON T1.id = T2.id_t1
INNER JOIN T3 ON T1.id = T3.id_t1
ORDER BY (CASE WHEN T2.[DateTime] > T3.[DateTime] THEN
T2.[DateTime]
ELSE
T3.[DateTime]
END) DESC
If you need to select field from T2 and T3, GROUP BY on all T1 field with aggregate on field from t2 and t3 is an option. Otherwise, linked-subquery is the way to go.
As sgeddes commented already, it's hard to know what you need, without seeing some example data from your tables. It would really help to know what the relationship between the three tables is.
One question I have, in particular, is: how are t2 and t3 related, if at all? It looks like they might not be, as each of them has its own datetime column.
Perhaps the following could do the job, but we need some more info to know for sure:
(SELECT DISTINCT t1.*, t2.id, t2.au_id, t2.re_id, t2.text, t2.`datetime`, t2.med_id, t2.ga_id, NULL AS pro_id
FROM t1
INNER JOIN t2 ON t1.id = t2.id_t1)
UNION
(SELECT DISTINCT t1.*, t3.id, t3.au_id, t3.re_id, t3.text, t3.`datetime`, NULL AS med_id, NULL AS ga_id, t3.pro_id
FROM t1
INNER JOIN t3 ON t1.id = t3.id_t1)
ORDER BY datetime DESC
LIMIT 10
The following selects the username and the datetime for the last ten posts.
SELECT username, last_ten.`datetime` AS lastpost
FROM t1
INNER JOIN (
SELECT 't2' AS tab, id, `datetime`, t2.id_t1
FROM t2
UNION ALL
SELECT 't3' AS tab, id, `datetime`, t3.id_t1
FROM t3
ORDER BY datetime DESC
LIMIT 10
) AS last_ten ON t1.id = last_ten.id_t1
Table 1: invTypes with columns typeID,groupID,typeName,description
Table 2: item_value with columns typeID,volume,avg,max,min,stddev,percentile,updated_on
I need to return all of the above columns where the latest updated_on (datetime) field as the deciding factor. I would like to return the latest datetime for each day with all of the information from table 1 and table 2 as the result.
This is how you get the rows corresponding to the most recent updated_on for each date in your item_value table:
SELECT
invTypes.*,
item_value.*
FROM
item_value
INNER JOIN
(
SELECT
MAX(updated_on) AS `updated_on`
FROM
item_value
GROUP BY
DATE(updated_on)
) latest
ON
latest.updated_on = item_value.updated_on
INNER JOIN
invTypes
ON
invTypes.typeID = item_value.typeID
ORDER BY
item_value.updated_on
SELECT * FROM table1
LEFT JOIN table1.uniqueid = table2.uniqueid ON table2
ORDER BY update_on DESC
GROUP BY (DATE(updated_on))