i have a mysql like this
SELECT * FROM table WHERE id IN(3245,76,3466,998,12984,4466,931,50,728)
is there any way i could get the results of the query ordered by the order the id's have in the IN clause?
Thanks a lot
UPDATE: i've just found this question covered here
Althought, my IN clause does contain up to 5000 id's, so would the use of 'FIELD' the best solution out there?
If you don't mind repeating the sequence of ids, using ORDER BY FIELD should do the trick:
SELECT * FROM table WHERE id IN(3245,76,3466,998,12984,4466,931,50,728)
ORDER BY FIELD (id,3245,76,3466,998,12984,4466,931,50,728)
As #vyegorov noted in the comments, for a large number of ids, you may have to create a temporary table to hold the actual order
CREATE TEMPORARY TABLE `temp_sort` (
`id` INT NOT NULL ,
`seq` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
PRIMARY KEY ( `seq` ) ,
UNIQUE ( `id` )
);
INSERT INTO temp_sort (id) VALUES (3245),(76),(3466);
SELECT * FROM table
INNER JOIN temp_sort ON (temp_sort.id=table.id)
ORDER BY temp_sort.seq;
Since you have up to 5000 items in your IN clause, you really need to make a separate table that contains a list of your ids that you want to include. Put an order column in that table and then do an inner join and order by the order column. That solves both problems.
Like so:
SELECT table.*
FROM table
INNER JOIN tblIDs ON tblIDs.id = table.id
ORDER BY tblIDs.OrderValue
Your new table (tblIDs) would look like this:
id OrderValue
3245 1
76 2
3466 3
By doing an INNER JOIN on the id columns, you will ensure that only those rows in your original table that have one of your listed id numbers will be displayed. The OrderValue column will allow you to easily and efficiently sort your query and it will also allow you to easily change the sort order without hacking a query apart.
Not unless you make those ids an attribute. And even then, it will order them asc/desc, not out of order like you have them.
try doing this.
SELECT your_column_name * FROM table WHERE id IN(3245,76,3466,998,12984,4466,931,50,728)
ORDER BY your_column_name
Related
So I've got a table with a primary key id and a foreign key target_id that points to an id. What I'm trying to do is set each target_id to a random id, that is not itself.
At the moment, this is how I get the randomized id's:
SELECT id FROM (SELECT id FROM test) AS sub ORDER BY RAND()
However, when I try to assign that subquery of randomized id's to the column target_id, an error is thrown saying that the subquery returns more than one row.
However, when I tried
UPDATE SET `target_id` = `id`
to see if columns can be directly copied, it worked, showing that IS possible. But why can't one column of my subquery be copied into a column of my table?
Sorry if I worded my question really weirdly; I'm not very experienced in MySql :/
Thanks! :D
As you might guess from the link in my comment to your question - I did not have time to explain further at the time ... - I assume that what you actually want is to shuffle the values of column target_id around. In Mysql this seems to be a non-trivial task, as the post in my comment shows.
I also played around a bit further and came up with this "variation of the theme" using user defined variables. I first tried using a temporary table, but this can only be referenced once so I had to revert to using a "conventional" table tmp in the end:
drop table if exists tmp;
select #n:=0;select #m:=0;
create table tmp select * from
(select *,#n:=#n+1 nr
from (select id,#m:=#m+1 n from tbl order by rand()) rnd
order by rand()
) rnd ;
update tbl s
inner join tmp a on a.id=s.id
inner join tmp b on b.nr=a.n
inner join tbl t on t.id=b.id
set t.target_id=s.target_id;
Check out the little demo here: http://rextester.com/XYF73480
I have one table stock activity where i have multiple records attached with single item_id. note item_id is playing foreign key role here in stock activity table . so actually i am tracking the item(in,out) of inventory. now i want to retrieve the last record activity stored in the table. i have written query which is supposed to be returning the last record from the table but it is returning the first record ..
Columns are :
activity_id pk
item_id fk
balance int(11)
Here is my query:
SELECT DISTINCT(item_id),balance
FROM `stock_activity`
GROUP BY (item_id)
ORDER BY(activity_id) DESC
Remember if a column that doesn't belongs to the grouping key is being referenced without any sort of aggregation so such statement is impossible.
So remember a little formula to came our this problem.
SELECT * FROM
(
SELECT * FROM `table`
ORDER BY AnotherColumn
) t1
GROUP BY SomeColumn
;
Modify your query like this and hope it will work fine!!!.
SELECT * FROM(
SELECT DISTINCT(item_id),balance
FROM `stock_activity`
ORDER BY(activity_id) DESC
) t1
GROUP BY (item_id)
This is a common problem folks have an issue with. you want the GROUPWISE MAXIMUM (or MINIMUM) of a column. Fortunately such an example exists right in the tutorial section of the manual
I wanted to know if there is an easy way to remove duplicates from a table sql.
Rather than fetch the whole table and delete the data if they appear twice.
Thank you in advance
This is my structure :
CREATE TABLE IF NOT EXISTS `mups` (
`idgroupe` varchar(15) NOT NULL,
`fan` bigint(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
If you are using Sql Server
Check this: SQL SERVER – 2005 – 2008 – Delete Duplicate Rows
Sample Code using CTE:
/* Delete Duplicate records */
WITH CTE (COl1,Col2, DuplicateCount)
AS
(
SELECT COl1,Col2,
ROW_NUMBER() OVER(PARTITION BY COl1,Col2 ORDER BY Col1) AS DuplicateCount
FROM DuplicateRcordTable
)
DELETE
FROM CTE
WHERE DuplicateCount > 1
GO
Add a calculated column that takes the checksum of the entire row. Search for any duplicate checksums, rank and remove the duplicates.
you can do something like this :
DELETE from yourTable WHERE tableID in
(SELECT clone.tableID
from yourTable origine,
yourTable clone
where clone.tableID= origine.tableID)
But in the WHERE, you can either compare the indexes or compare each other fields...
depending on how you find your doubles.
note, this solution has the advantage of letting you choose what IS a double (if the PK changes for example)
You can find the duplicates by joining the table to itself, doing a group by the fields you are looking for duplicates in, and a having clause where count is greater than one.
Let's say your table name is customers, and your looking for duplicate name fields.
select cust_out.name, count(cust_count.name)
from customers cust_out
inner join customers cust_count on cust_out.name = cust_count.name
group by cust_out.name
having count(cust_count.name) > 1
If you use this in a delete statement you would be deleting all the duplicate records, when you probably intend to keep on of the records.
So to select the records to delete,
select cust_dup.id
from customers cust
inner join customers cust_dup on cust.name = cust_dup.name and cust_dup.id > cust.id
group by cust_dup.id
I have a table with data that I don't need to keep for very long, so every night I want to remove all rows except the last 20.
To do that, I found the following query:
DELETE FROM Table WHERE ID NOT IN (
SELECT id FROM (
SELECT TOP 10 ID FROM Table
) AS x
)
MySQL doesn't support the TOP function, so I rewrote it to use LIMIT instead:
DELETE FROM Table WHERE ID NOT IN (
SELECT id FROM (
SELECT ID FROM Table ORDER BY ID DESC LIMIT 10
) AS x
)
Unfortunately, MySQL doesn't seem to support the LIMIT function within subqueries. So what do I do now?
How do I select all except the 10 rows with the highest ID?
I could probably just delete all the records that are older than a day or something, but it feels like I should be able to do it this way.
As MySQL has foibles when reading from the same table as you are deleting, the simplest option is often to use a temp table.
INSERT INTO yourTempTable
SELECT id FROM yourTable
ORDER BY ID DESC LIMIT 10
DELETE yourTable WHERE id IN (SELECT id FROM yourTempTable)
Or many variations thereof (using joins instead of IN, etc).
The main consideration isn't about how to write the second query, it's about race conditions.
Your data could be changed by another process between the temp table and the delete. If that is possible and matters, you need to wrap it all in a transaction and slap a table lock on yourTable.
Another way:
DELETE t
FROM
TableX AS t
CROSS JOIN
( SELECT Id
FROM TableX
ORDER BY Id DESC
LIMIT 1 OFFSET 9
) AS tenth
WHERE t.Id < tenth.id
There are few ways to do this, I would prefer this :-
create table tmp_table select * from your_table order by id desc limit 20;
truncate table your_table;
insert into your_table select * from tmp_table;
drop table tmp_table;
It seems very lengthy at first glance,
but personally I think is understandable,
and very low risk (plus, it should be efficient that doing a JOIN)
PS : truncate won't reset auto increment field
ps2 : this approach assume there is no write during truncate, one can issue lock to preserve the data integrity
I need some help with this query: I want to delete the following rows from my table.
The table has 4 columns: UserID, UserName, Tag, Score.
I want to keep only the top 1000 users with highest score, for each Tag.
So I need to order by score, and to keep the first 1000 users for each tag.
Thanks
Based on the other answer,
DELETE FROM table t1
WHERE UserID NOT IN (SELECT userID FROM table t2
WHERE t2.tag = t1.tag
ORDER BY Score DESC LIMIT 1000);
This assumes that UserID is a unique/primary key field. If it's not, you could do something like this:
DELETE FROM table t1
WHERE UserID||' '||Tag NOT IN (SELECT UserID||' '||Tag FROM table t2
WHERE t2.tag = t1.tag
ORDER BY Score DESC LIMIT 1000);
Putting the spaces in because I know I've had to do similar on Oracle, not sure how MySQL would handle it without.
You should be able to fix this with a subquery although I'm not completely sure if MySQL supports that within delete queries. I do know that it can give problems with update queries (I've had some segfaults in MySQL because of this)
Either way... this should work (atleast, it would in Postgres)
DELETE FROM table WHERE id NOT IN (SELECT id FROM table ORDER BY Score DESC LIMIT 1000)
Assuming that id is your primary key ofcourse.
Solution using a temporary table:
Do note that you'll have to repeat this process for every tag. I can't think of a way to do it in 1 query in MySQL 5.0
CREATE TEMPORARY TABLE top_users
SELECT * FROM table
WHERE Tag = ...
GROUP BY UserID
ORDER BY Score DESC
LIMIT 1000;
DELETE FROM table WHERE Tag = ...;
INSERT INTO table
SELECT * FROM top_users;
Maybe a temporary table, who is filled with a select clause
SELECT * FROM table ORDER BY Score DESC LIMIT 1000;
I dont have the syntax handy for creating the temporary table, but that will atleast get your the rows you want.
Be careful with delete commands... Better to create a new view/table.