How can I SELECT the last row in a MySQL table?
I'm INSERTING data and I need to retrieve a column value from the previous row.
(I'm using PHP by the way.)
the table1 something like this
table1
******************
cate_id | task_id | start_date | end_date | line |
1 2 30/04/2012 26/06/2012 text
3 1 26/06/2012 27/06/2012 text
2 1 27/06/2012 01/01/9999 text
There'sNO an auto_incrementin that table.
And my case is to update the existing last row in table and then insert a new one.
You've edited question so, here's update
SELECT MAX(cate_id) AS last_cate_id FROM table;
or you can get next ID by:
SELECT MAX(cate_id)+1 AS next_cate_id FROM table;
Without transactions this is very vulnerable for inserting same cate_id!
If you cant use them, for example because of MyISAM, you could insert with select.
INSERT INTO table
(cate_id, task_id ..)
VALUES
( (SELECT MAX(cate_id)+1 AS next_cate_id FROM table), 1 )
if you don't have order by you wont be able to get the "LAST" value or the first, because the order will not be the same (necessarily), if you don't have auto increment how can you know which one is the first or the last?, if you are working with date or auto increment you will be able to get that, however, lets say that you have a order by 'column1' you can do something like:
select * from table1 order by `column1` desc limit 1
Related
Is it possible to sort in MySQL by "order by" using a predefined set of column values (ID) like order by (ID=1,5,4,3) so I would get records 1, 5, 4, 3 in that order out?
UPDATE: Why I need this...
I want my records to change sort randomly every 5 minutes. I have a cron task to update the table to put different, random sort order in it.
There is just one problem! PAGINATION.
I will have visitors who come to my page, and I will give them the first 20 results. They will wait 6 minutes, go to page 2 and have the wrong results as the sort order has already changed.
So I thought that if I put all the IDs into a session on page 2, we get the correct records even if the sorting had already changed.
Is there any other better way to do this?
You can use ORDER BY and FIELD function.
See http://lists.mysql.com/mysql/209784
SELECT * FROM table ORDER BY FIELD(ID,1,5,4,3)
It uses Field() function, Which "Returns the index (position) of str in the str1, str2, str3, ... list. Returns 0 if str is not found" according to the documentation. So actually you sort the result set by the return value of this function which is the index of the field value in the given set.
You should be able to use CASE for this:
ORDER BY CASE id
WHEN 1 THEN 1
WHEN 5 THEN 2
WHEN 4 THEN 3
WHEN 3 THEN 4
ELSE 5
END
On the official documentation for mysql about ORDER BY, someone has posted that you can use FIELD for this matter, like this:
SELECT * FROM table ORDER BY FIELD(id,1,5,4,3)
This is untested code that in theory should work.
SELECT * FROM table ORDER BY id='8' DESC, id='5' DESC, id='4' DESC, id='3' DESC
If I had 10 registries for example, this way the ID 1, 5, 4 and 3 will appears first, the others registries will appears next.
Normal exibition
1
2
3
4
5
6
7
8
9
10
With this way
8
5
4
3
1
2
6
7
9
10
There's another way to solve this. Add a separate table, something like this:
CREATE TABLE `new_order` (
`my_order` BIGINT(20) UNSIGNED NOT NULL,
`my_number` BIGINT(20) NOT NULL,
PRIMARY KEY (`my_order`),
UNIQUE KEY `my_number` (`my_number`)
) ENGINE=INNODB;
This table will now be used to define your own order mechanism.
Add your values in there:
my_order | my_number
---------+----------
1 | 1
2 | 5
3 | 4
4 | 3
...and then modify your SQL statement while joining this new table.
SELECT *
FROM your_table AS T1
INNER JOIN new_order AS T2 on T1.id = T2.my_number
WHERE ....whatever...
ORDER BY T2.my_order;
This solution is slightly more complex than other solutions, but using this you don't have to change your SELECT-statement whenever your order criteriums change - just change the data in the order table.
If you need to order a single id first in the result, use the id.
select id,name
from products
order by case when id=5 then -1 else id end
If you need to start with a sequence of multiple ids, specify a collection, similar to what you would use with an IN statement.
select id,name
from products
order by case when id in (30,20,10) then -1 else id end,id
If you want to order a single id last in the result, use the order by the case. (Eg: you want "other" option in last and all city list show in alphabetical order.)
select id,city
from city
order by case
when id = 2 then city else -1
end, city ASC
If i had 5 city for example, i want to show the city in alphabetical order with "other" option display last in the dropdown then we can use this query.
see example other are showing in my table at second id(id:2) so i am using "when id = 2" in above query.
record in DB table:
Bangalore - id:1
Other - id:2
Mumbai - id:3
Pune - id:4
Ambala - id:5
my output:
Ambala
Bangalore
Mumbai
Pune
Other
SELECT * FROM TABLE ORDER BY (columnname,1,2) ASC OR DESC
I have a basic SQL problem that's been driving me mad. If I have a mySQL table e.g below.
How would I add another 80+ values to Column 2 starting from the first empty row (in this example row 3).
I've been trying a number of queries using INSERT or UPDATE but the closest I've got is to add the values to column 2 starting from the last defined ID value (e.g. row 80ish).
ID | Column 2 |
--------------------------------
1 | value |
2 | value |
3 | |
4 | |
5 | |
etc
The real table has around 10 columns, all with data in but I just need to add content (a list of around 80 different strings in CSV format to one of the columns)
I'd appreciate it if anyone could point me in the right direction.
I'd load the data into a separate table with the same structure and then update the target table using join or subquery to determine which columns are currently empty.
i.e. load interim table and then:
update target_table set column2 = (select column2 from interim_table where ...
where column2 is null
(slow but intuitive)
update target table, interim_table
set target table.column2 = interim_table.column2
where target table... = interim_table...
and target_table.column2 is null
(better performance)
Why don't you first run a query to find out the first empty row ID number? you can use SELECT COUNT(*)
FROM TABLE_NAME for that.
then you create a for loop and inside run a INSERT query, starting with the value returned by the previous query. just a scratch:
for(var id = last; id < totalOfQueries; id++)
{
var query = new MysqlCommand("INSERT INTO table VALUES ('" + id + "',....);
}
hi I'm looking for a way to only show a matching set of mysql results only once. can anyone tell me how to do this?
here's an example of what i'm trying to achieve:
id | profile_id | viewed_profile_id | date_viewed
1 4 7 00:00:00
2 5 6 00:00:00
1 4 7 00:00:00
so if profile_id and viewed_profile_id match then to only show one result for those matching columns rather than twice or three times or however many times it appears in the database?
Use the DISTINCT keyword:
SELECT DISTINCT id, profile_id, viewed_profile_id, date_viewed
FROM myTable
This will show only one row for each unique combination of the columns selected.
Or, reading into your question a lot (since you only want to match profile_id and viewed_profile_id), if you want to show the latest date viewed for each viewer, you can use GROUP BY and select the MAX date viewed. I am also assuming there is data in date_viewed and it is sortable:
SELECT profile_id, viewed_profile_id, MAX(date_viewed)
FROM myTable
GROUP BY profile_id, viewed_profile_id
DISTINCT helps to eliminate duplicates. If a query returns a result that contains duplicate rows, you can remove duplicates to produce a result set in which every row is unique. To do this, include the keyword DISTINCT after SELECT and before the output column list
http://dev.mysql.com/doc/refman/5.0/en/distinct-optimization.html
SELECT DISTINCT(` profile_id`),`viewed_profile_id`,`id`,`date_viewed` FROM `tableName` GROUP BY `viewed_profile_id`
try this:
$query = "SELECT * FROM TABLENAME WHERE profile_id = '$PROFILEIDVALUE' AND viewed_profile_id = '$VIEWEDIDVALUE' LIMIT 0, 1"
Depending upon the ORDER you want use can use ORDER BY id DESC/ASC
I hope this would be useful
I think most people had serious problems with inserting a value/data into a database (mysql). When I'm inserting a value into a database, I assign an unique id (INT) for that line. When I query the database, easily I can read/modify/delete that line.
With function for() (in php) I easily can read values/data from the database. The problem occurs when I delete a line (in the middle for example).
E.g:
DB:
ID | column1 | column2 | ... | columnN
--------------------------------------
1 | abcdefgh | asdasda | ... | asdasdN
2 | asdasddd | asdasda | ... | asdasdN
...
N | asdewfew | asddsad | ... | asddsaN
php:
for($i = 0; $i <= $n; $i++){
$sql = mysql_query("SELECT * FROM db WHERE ID = '$i' ");
//Code;
}
*$n = last column value from ID
Am I need to reorganize the entire database to have a correct "flow" (1, 2, 3, .. n)? Or am I need to UPDATE the each cell?
What you're doing here is unnecessary thanks to AUTO_INCREMENT in mysql. Run this command from PhpMyAdmin (or another DB management system):
ALTER TABLE db MODIFY COLUMN ID INT NOT NULL AUTO_INCREMENT;
Now when insert a row into db mysql will assign the ID for you:
INSERT INTO db (id, column1, column2) VALUES(NULL, 'abc', 'def');
SELECT * FROM db;:
+--+-------+-------+
|id|column1|column2|
+--+-------+-------+
|1 |old |oldrow |
+--+-------+-------+
|2 |abc |def | <--- Your newly inserted row, with unique ID
+--+-------+-------+
If you delete a row, it is true that there will be an inconsistency in the order of the ID's, but this is ok. IDs are not intended to denote the numeric position of a row in a table. They are intended to uniquely identify each row so that you can perform actions on it and reference it from other tables with foreign keys.
Also if you need to grab a group of ID's (stored in an array, for example), it is much more efficient to perform one query with an IN statement.
$ids = array(1,2,3,4,5,6);
$in = implode(',', $ids);
mysql_query('SELECT * FROM db WHERE id IN ('.$in.')');
However, if you want all rows just use:
SELECT * FROM dbs;
But be weary of bobby tables.
You can select all the rows with query
SELECT * FROM db
and do whatever you want after
You can never ensure, that the ids are continous. As you noticed yourself there are gaps after you delete a row, but even for example when you insert rows within a transaction and don't commit it, because something failed and you need to revert the transaction. An ID is an identifier and not row number.
For example if you want to select X items from somewhere (or such) have a look at LIMIT and OFFSET
SELECT * FROM mytable ORDER BY created DESC LIMIT 10 OFFSET 20;
This selects the rows 21 to 30 ordered by their creation time. Note, that I don't use id for ordering, but you cannot rely on it (as mentioned).
If you really want to fetch rows by their ID you definitely need to fetch the IDs first. You may also fetch a range of IDs like
SELECT * FROM mytable WHERE id IN (1,2,3,4);
But don't assume, that you will ever receive 4 rows.
Ids are surrogate keys–they are in no way derived from the data in the rest of the columns and their only significance is each row has a unique one. There's no need to change them.
If you need a specific range of rows from the table, use BETWEEN to specify them in the query:
SELECT id, col1, col2, ..., coln
FROM `table`
WHERE id BETWEEN ? AND ?
ORDER BY id
If you need all the rows and all columns for that table use:
$query = mysql_query("SELECT * FROM table_name");
and then loop through each row with a while statement:
while ($row = mysql_fetch_array($query ))
{
echo $row['column_name'];
}
You do not have to reorganize the entire database in order to keep the index. But if you feel like it, you'd have to update each cell.
BTW, look at mysql_fetch_array(), it will ease the load on the SQL server.
I have a MySQL query that looks like this:
UPDATE `Table` SET `Column` =
CASE
WHEN `Option Id` = '1' THEN 'Apple'
WHEN `Option Id` = '2' THEN 'Banana'
WHEN `Option Id` = '3' THEN 'Q-Tip'
END
An my table currently looks like this:
Option Id | Column
1 | x
2 | x
I'd like it to result in:
Option Id | Column
1 | Apple
2 | Banana
3 | Q-Tip
But it doesn't insert the Q-Tip row. I've looked up and read a bit about INSERT ON DUPLICATE KEY UPDATE and REPLACE, but I can't find a way to get those to work with this multiple row update using CASE. Do I have to write a separate query for each row to get this to work, or is there a nice way to do this in MySQL?
Option Id is not a Key itself, but it is part of the Primary Key.
EDIT Some more info:
I'm programming in PHP, and essentially I'm storing an array for the user. Option Id is the key, and Column is the value. So for simplicities sake, my table could look like:
User Id | Option Id | Value
10 | 1 | Apple
10 | 2 | Shoe
11 | 1 | Czar
...
That user can easily update the elements in the array and add new ones, then POST the array to the server, in which case I'd like to store it in the table. My query above updates any array elements that they've edited, but it doesn't insert the new ones. I'm wondering if there is a query that can take my array from POST and insert it into the table without me having to write a loop and have a query for every array element.
This should work, if Option_Id is a primary key:
REPLACE INTO `Table` (`Option_Id`, `Column`) VALUES
(1, 'Apple'),
(2, 'Banana'),
(3, 'Q-Tip');
The statement means: Insert the given rows or replace the values, if the PK is already existing.
Of course it does not insert. As there is no such value, it cannot get updated.
I suppose you are normalizing a database by putting in the values already present and now want to add the required mapping for every valid value.
So it would be better to start from scratch and just do INSERTs.
You could always query the database for entries and then choose update or insert based on yor results
I see no point in such updating.
Why don't you have a separate table with option ids and corresponding values, leaving only option ids linked to user ids in this one?