I have a database that stores a history of transactions, mostly comment updates. Therefore, I accept multiple records with the same ID.
What I need to do is pull in all of the records and display the most recent of each record.
Here is an example of 2 records with the same UID. The highlighted record is the most recent of the 2.
Here is one of the queries I attempted:
SELECT
uid
,voyage
,MAX(comments)
,MAX(edituser)
,MAX(editdate)
FROM
table
GROUP BY
uid
ORDER BY
uid
Here is the same UID that is returned:
If you'll notice, it is the most recent user and editdate, but it's not the most recent comment, which should be 'THIS IS A TEST COMMENT'.
I have tried several queries, but this is the closest I've gotten to returning the most recent of every record.
I tried this link: SQL Select record with most recent date
But I don't think I need to use any JOINS in this case, being that everything is in the same table.
How can I make this work?
With something like this, you are probably better off using sub-selects.
SELECT
t1.uid,
t1.voyage,
(SELECT comments FROM table t2 WHERE t2.uid = t1.uid AND t2.editdate = MAX(t1.editdate) LIMIT 1) as comments,
(SELECT edituser FROM table t2 WHERE t2.uid = t1.uid AND t2.editdate = MAX(t1.editdate) LIMIT 1) as edituser,
(SELECT editdate FROM table t2 WHERE t2.uid = t1.uid AND t2.editdate = MAX(t1.editdate) LIMIT 1) as editdate,
FROM table t1
GROUP BY t1.uid
ORDER BY t1.uid
Each sub-select narrows it down to the same uid, and then takes the one with the most recent editdate.
If that's what your desired output be then you should use MIN() instead like MIN(comments)
Change your order by to editdate by descending:
... ORDER BY editdate DESC
Related
i have two tables in a DB with the following structure:
table 1: 3 rows - category_id, product_id and position
table 2: 3 rows - category_id, product_id and position
i am trying to set table 1 position to table 2 position where category and product id is the same from the tables.
below is the sql i have tried to make this happen but returns MySQL error 1242 - subquery returns more then 1 row
UPDATE table1
SET position = (
SELECT position
FROM table2
WHERE table1.product_id = table2.product_id AND table1.category_id = table2.category_id
)
The solution is very simple and it can be done in two simple steps. The first step is just a preview of what will be changed, to avoid destroying data. It can be skipped if you are confident of your WHERE clause.
Step 1: preview the changes
Join the tables using the fields you want to match, select everything for visual validation of the match.
SELECT t1.*, t2.*
FROM table1 t1
INNER JOIN table2 t2
ON t1.category_id = t2.category_id
AND t1.product_id = t2.product_id
You can also add a WHERE clause if only some of the rows must be modified.
Step2: do the actual update
Replace the SELECT clause and the FROM keyword with UPDATE, add the SET clause where it belongs. Keep the WHERE clause:
UPDATE table1 t1
INNER JOIN table2 t2
ON t1.category_id = t2.category_id
AND t1.product_id = t2.product_id
SET t1.position = t2.position
That's all.
Technical considerations
Indexes on the columns used on the JOIN clause on both tables are a must when the tables have more than several hundred rows. If the query doesn't have WHERE conditions then MySQL will use indexes only for the biggest table. Indexes on the fields used on the WHERE condition will speed up the query. Prepend EXPLAIN to the SELECT query to check the execution plan and decide what indexes do you need.
You can add SORT BY and LIMIT to further reduce the set of changed rows using criteria that cannot be achieved using WHERE (for example, only the most recent/oldest 100 rows etc). Put them on the SELECT query first to validate the outcome then morph the SELECT into an UPDATE as described.
Of course, indexes on the columns used on the SORT BY clause are a must.
You can run this query to see what is happening:
SELECT product_id, category_id, count(*), min(position), max(position)
FROM table2
GROUP BY product_id, category_id
HAVING COUNT(*) > 1;
This will give you the list of product_id, category_id pairs that appear multiple times in table2. Then you can decide what to do. Do you want an arbitrary value of position? Is the value of position always the same? Do you need to fix the table?
It is easy enough to fix the particular problem by using limit 1 or an aggregation function. However, you may really need to fix the data in the table. A fix looks like:
UPDATE table1 t1
SET t1.position = (SELECT t2.position
FROM table2 t2
WHERE t2.product_id = t1.product_id AND t2.category_id = t1.category_id
LIMIT 1
);
I want to making a MySQL query that gets a link from table1 and checks to see if this link exists in table2 and table3.
Now I am doing 2 queries, but I would like to combine the 2 query into 1, and guarantee 10 results are returned? (After the first, currently, if mysql_num_rows($rez)>0, the return result would be less 10)
Thanks.
$result = mysql_query("SELECT id,link FROM table1 WHERE Order By id DESC LIMIT 0,10");
while ($row = mysql_fetch_array($result)){
$rez = mysql_query("(SELECT link FROM table2 WHERE link='".mysql_real_escape_string($row['link'])."') UNION (SELECT link FROM table3 WHERE link='".mysql_real_escape_string($row['link'])."')");
if(mysql_num_rows($rez)==0){
//do stuff with $row['link'];
}
}
You can use sub-queries to acomplish this
SELECT id, link FROM table1 WHERE (link IN (SELECT link FROM table2)) OR (link IN (SELECT link FROM table3)) LIMIT 10
My format might be slightly off, and it seems like there's probably a better way to do that query, but check out sub-queries as I think those will get you in the direction you want to go
Assuming you're asking to find rows that don't exist in table2 or table3.
If you're trying to find rows that exist in either, use the query posted above.
SELECT id, link FROM table1 WHERE link NOT IN (SELECT link FROM table2) AND link NOT IN (SELECT link FROM table3) ORDER BY id DESC LIMIT 0,10
I'm fairly new to MYSQL!
I need to make a SQL query where i check how many likes a row has (between two tables)
I found another question that looked like mine, but i can't get it to return anything (even though it doesn't create an error.
query:
SELECT *
FROM likes
INNER JOIN (SELECT likes.like_id,
COUNT(*) AS likes
FROM likes
INNER JOIN uploads ON likes.upload_id=uploads.upload_id
WHERE uploads.upload_date >= DATE_SUB(CURDATE(), INTERVAL 8 DAY)
GROUP BY uploads.upload_id) x ON x.like_id = likes.like_id
ORDER BY x.likes DESC
Link to the original question:
MySQL, Need to select rows that has the most frequent values in another table
Help is much appreciated
Kind regards,
Mathias
Since you didn't post your table structure I'll have to guess..
select someid, count(*) cnt from
(
select * from table1 t1 join table2 t2 on t1.someid = t2.someid
) as q0 group by someid order by cnt desc;
It will need tweaking to fit your schema.
I'm using a database to store results of an election with the columns id, candidate, post_time and result. Results are put in the database during 'counting the votes'. When a new update is available, a new entry will be inserted.
From this database, I would like to create a table with the most recent results (MAX post_time) per candidate (GROUP BY candidate), ordered by result (ORDER BY result).
How can I translate this to a working SQL-statement?
(I've tried mysql order and groupby without success)
I've tried:
SELECT *, MAX(time_post)
FROM [database]
GROUP BY candidate
HAVING MAX(time_post) = time_post
ORDER BY result
Assuming that you don't have multiple results per candidate at same time, next should work:
select r.candiate, r.result
from results r
inner join (
select candidate, max(post_time) as ptime
from results
group by candidate
) r2 on r2.candiate=r.candidate and r2.ptime=r.post_time
order by r.result
Note that MAX will not select the record with the maximum time, but it will select the maximum value from any record. So
SELECT MAX(a), MAX(b) FROM example
where exmple contains the two records a=1, b=2 and a=4, b=0, will result in a=4, b=2, which wasn't in the data. You should probably create a view with the latest votes only from each candidate, then query that. For performance, it may be sensible to use a materialized view.
Is the post_time likely to be the same for all the most recent results? Also does each candidate only appear once per post_time?
This could be achieved by just using a SELECT statement. Is there a reason you need the results in a new table?
If each candidate only appears once per post_time:
SELECT candidate, result
FROM table
WHERE post_time = (SELECT MAX(post_time) FROM table)
If you want to count how many times a candidate appears in the table for the last post_time:
SELECT candidate, count(result) as ResultCount
FROM table
WHERE post_time = (SELECT MAX(post_time) FROM table)
GROUP BY candidate
By what i see from ur attempts i'd think you should use this
SELECT MAX(post_time) FROM `table` GROUP BY candidate ORDER BY result
but the MAX statment only return a single value therefore i dont see why ORDER BY would be needed.
if you want multiple results try looking up the TOP statment
One way (tied results shown):
SELECT t.*
FROM tableX AS t
JOIN
( SELECT candidate
, MAX(time_post) AS time_post
FROM tableX
GROUP BY candidate
) AS m
ON (m.candidate, m.time_post) = (t.candidate, t.time_post)
ORDER BY t.result
and another one (no ties, only one row per candidate shown):
SELECT t.*
FROM
( SELECT DICTINCT candidate
FROM tableX
) AS d
JOIN
tableX AS t
ON t.PK = --- the Primary Key of the table, here
( SELECT ti.PK --- and here
FROM tableX AS ti
WHERE ti.candidate = d.candidate
ORDER ti.time_post DESC
LIMIT 1
)
ORDER BY t.result
I have some tables with various content. What I want to accomplish is to display the lets say 20 latest entries from those tables in a div.
Here is my first table - audio1
userID folder title date
the two other folders look exactly the same
audio2
userID folder title date
audio3
userID folder title date
How can I get the data from all the tables at the same time and echo them one by one to a div ordered by date with PHP?
SELECT userID, folder, title, date
FROM audio1
UNION ALL
SELECT userID, folder, title, date
FROM audio2
UNION ALL
SELECT userID, folder, title, date
FROM audio3
ORDER BY date DESC LIMIT 20;
Your SQL query will be a 3 part UNION. A UNION query concatenates results from multiple tables with (usually) similar structures, when a JOIN relationship is not needed but rather you just need to return rows from multiple tables.
$sql = "SELECT userID, folder, title, date FROM audio1
UNION ALL
SELECT userID, folder, title, date FROM audio2
UNION ALL
SELECT userID, folder, title, date FROM audio3
LIMIT 20;";
$result = mysql_query($sql);
if ($result) {
// Fetch results and echo them into a list.
}
You will need a column to ORDER BY. This is likely to be date, but you may have other plans. Add an ORDER BY clause before the LIMIT 20.
it seems that your database setup is wrong and you have to have only one table called 'audio' with a field represents the number you are currently using in the table name.
You may try the union, or you can try a join.
SELECT
COALESCE(t1.userID, t2.userID, t3.userID) as userID
, t1.folder, t1.title, t1.date
, t2.folder, t2.title, t2.date
, t3.folder, t3.title, t3.date
FROM table1 t1
FULL OUTER JOIN table2 t2 ON (t1.userID = t2.userID)
FULL OUTER JOIN table3 t3 ON (t1.userID = t3.userID)
It's a very different beast, so I'd thought I'd give you the option.