I have a table with some columns and I want to order the selection by the column 'post_id'. The rows are like this: 'rgpost0', 'rgpost1','rcpost2', ...
How can I order the selection by the number at the end of the value of the column 'post_id' descending?
This code is not working: SELECT * FROM posts_info ORDER BY post_id+0 DESC
I don't want to change the column type to number. I just want to order by number at the end of the string.
You can use reverse() twice:
SELECT * FROM posts_info
ORDER BY reverse(reverse(post_id) + 0) + 0 DESC
For this table:
create table posts_info(id int, post_id varchar(100));
insert into posts_info(id, post_id) values
(1, 'bob52'),
(2, 'alice634'),
(3, 'john12'),
(4, 'mark7'),
(5, 'mary001');
Results:
| id | post_id |
| --- | -------- |
| 2 | alice634 |
| 1 | bob52 |
| 3 | john12 |
| 4 | mark7 |
| 5 | mary001 |
See the demo.
If you are using MySQL 8+ then we can use REGEXP_SUBSTR here:
SELECT *
FROM posts_info
ORDER BY
CAST(REGEXP_SUBSTR(post_id, '[0-9]+$') AS UNSIGNED) DESC,
post_id DESC;
I added a second sorting level in case two post_id happen to end in the same number. In this case, I order descending by the entire post_id.
Try this
SELECT * FROM posts_info ORDER BY CAST(SUBSTR(post_id, 7) AS UNSIGNED) DESC;
Related
The table
The query
SELECT
id, MAX(fecha_hora_carga) AS fecha_hora_carga
FROM
calibraciones_instrumentos
GROUP BY
instrumento_id
The result
Its returning the most recent fecha_hora_carga dates, but the ids are 24 and 28...i think they should be 27 and 29!
Why are the ids not corresponding with the date?
The problem is MySQL does not make much sense when grouping by a max value.
It grabs the max column and then the other columns in that table you selected by whatever order you sort them by.
To get what you want, you have to use subqueries to pull the data you want.
Here is an example:
SELECT
t1.id,
t1.fecha_hora_carga
FROM
calibraciones_instrumentos AS t1
JOIN(
SELECT MAX(fecha_hora_carga) AS fecha_hora_carga,
instrument_id
FROM
calibraciones_instrumentos
GROUP BY
instrument_id
) AS t2
ON (t1.fecha_hora_carga = t2.fecha_hora_carga AND
t1.instrument_id = t2.instrument_id
);
Because you are misusing SQL. You have one column in the GROUP BY clause and that column isn't even being selected!
In most databases -- including the most recent versions of MySQL -- your query would generate a syntax error because id is neither in the GROUP BY nor an argument to an aggregation function such as MIN().
So, MySQL is providing just an arbitrary id. I would expect an aggregation query to look like this:
SELECT instrumento_id, MAX(fecha_hora_carga) AS fecha_hora_carga
FROM calibraciones_instrumentos
GROUP BY instrumento_id;
Or, if you want the row with the maximum fecha_hora_carga for each instrumento_id, use filtering:
select ci.*
from calibraciones_instrumentos ci
where ci.fecha_hora_carga = (select max(ci2.fecha_hora_carga)
from calibraciones_instrumentos ci2
where ci2.instrumento_id = ci.instrumento_id
);
This is because your query is incorrect
The MAX is an aggregate function and gets the max. value from the fecha_hora_carga, this won't give you the corresponding id too it just gets the maximum value stored in the fecha_hora_carga column, not a row.
See the following sample:
mysql>CREATE TABLE test_group_by (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, val1 INT, val2 INT);`
mysql>INSERT INTO test_group_by (val1, val2) VALUES(10,1), (6, 1), (18, 1), (22, 2), (4, 2);
mysql> SELECT * FROM test_group_by;
+----+------+------+
| id | val1 | val2 |
+----+------+------+
| 1 | 10 | 1 |
| 2 | 6 | 1 |
| 3 | 18 | 1 |
| 4 | 22 | 2 |
| 5 | 4 | 2 |
+----+------+------+
mysql> SELECT id, MAX(val1) FROM test_group_by GROUP BY val2;
+----+-----------+
| id | MAX(val1) |
+----+-----------+
| 1 | 18 |
| 4 | 22 |
+----+-----------+
As you can see in the example, that is a simplified representation of your table.
The MAX function does not retrieves a entry, just the max. value of all the entries in the table. But your query also asks for a ID, it just makes one up (which ID is returned cannot be said for sure).
I have a table with a column to maintain the state of the record. i.e.
-----------------------------
| id | desc | state |
-----------------------------
| 1 | desc 1 | Complete |
| 2 | desc 2 | Open |
| ... | ... | ... |
-----------------------------
I want fetch the records in the order of 'Open' followed by 'Complete'. Can I get this done using one SQL query? If so, how should I write it?
Yes, you could do this with the ORDER BY statement and FIELD function:
SELECT * FROM table1 ORDER BY FIELD(state, 'Open', 'Complete')
Try something like this:
select *
from table_name
order by decode (state, 'Open', 1, 'Complete', 2, 3)
Say you have a dynamic view of a table that consists of the following entries
| id | type |
| 1 | cat |
| 2 | dog |
| 3 | bunny|
The catch with this is that sometimes there may not be an id with a type of "cat" it could potentially look like
| id | type |
| 1 | dog |
| 2 | bunny|
How would one write a query for this table to select a single row based on precedence of type.
For example, if the ranking of type was cat > dog > bunny, I would want the first entry from that table with the highest ranking condition.
If we call our view pets, which has ORDER BY id ASC then we would have a query that looks something like this
SELECT *
FROM pets
WHERE type = 'cat' > 'dog' > 'bunny' -- here is where I need help
LIMIT 1
I've tried things like
IF EXISTS (SELECT *
FROM pets
WHERE type = "cat")
THEN SELECT * FROM pets WHERE condition = "cat" LIMIT 1
-- etc... down the ranking
Can't seem to get this to work though. Help is much appreciated.
In MySQL, I would use field():
SELECT *
FROM pets
WHERE type IN ('cat', 'dog', 'bunny')
ORDER BY field(type, 'cat', 'dog', 'bunny')
LIMIT 1
If you don't want to deal with the WHERE clause, you can do:
SELECT *
FROM pets
ORDER BY field(type, 'bunny', 'dog', 'cat') DESC
LIMIT 1
You need to go backwards because non-matches are returned as 0.
You can try to use CASE WHEN make the order number in ORDER BY, do your customer order by then LIMIT 1
CREATE TABLE pets(
ID INT,
type VARCHAR(50)
);
INSERT INTO pets VALUES ( 1 , 'cat');
INSERT INTO pets VALUES ( 2 , 'dog');
INSERT INTO pets VALUES ( 3 , 'bunny');
INSERT INTO pets VALUES ( 4 , 'TST');
Query 1:
SELECT *
FROM pets
ORDER BY CASE
WHEN type = 'cat' THEN 1
WHEN type = 'dog' THEN 2
WHEN type = 'bunny' THEN 3
ELSE 4
END
LIMIT 1
Results:
| ID | type |
|----|------|
| 1 | cat |
We have a DB called transaction. It has user_id, date, value and so on. I use pagination in my query also. I have thousands of record in my table which has user_id equal to 2 or other value. put the user_id = 2 at the very last page.
I want to sort the result like this:
sort the results by date but if the user_id= 2 , put all results associated with the user_id= 2 at the end.
to be more clear, I show you what I want in the below.
-------------------------------------
| ID | user_id | date | ......
-------------------------------------
| 1 | 10 | 2018-10-20 |
-------------------------------------
| 2 | 11 | 2018-10-21 |
-------------------------------------
| 3 | 2 | 2018-10-22 |
-------------------------------------
| 4 | 2 | 2018-10-23 |
the results have to be like this:
first: ID = 2, second: ID = 1, third: ID = 4, last: ID = 3
tip *:
I use field function but unfortunately in vain.
ORDER BY FIELD(user_id, 2) DESC, date DESC
You may try using a CASE expression in your ORDER BY clause:
SELECT *
FROM yourTable
ORDER BY
CASE WHEN user_id = 2 THEN 1 ELSE 0 END,
date DESC;
I'm not sure if you want each group sorted by date ascending or descending. If you want ascending date order, then remove the DESC keyword at the end of my query.
I have MySQL rows like this
id | title | desc | view
1 | i'm a title | i'm a desc | 0
2 | i'm a title | i'm a desc | 0
3 | i'm a title | i'm a desc | 5
4 | i'm a title | i'm a desc | 0
5 | i'm a title | i'm a desc | 0
6 | i'm a title | i'm a desc | 3
8 | i'm a title | i'm a desc | 0
And i would like to keep only
3 | i'm a title | i'm a desc | 5
because this record as the max view and others are duplicates
If your data is not too big, you can use delete like this:
delete t from yourtable t join
(select title, `desc`, max(view) as maxview
from yourtable t
group by title, `desc`
) tt
on t.title = tt.title and
t.`desc` = tt.`desc` and
t.view < tt.maxview;
Note: if there are multiple rows with the same maximum number of views, this will keep all of them. Also, desc is a lousy name for a column because it is a SQL (and MySQL) reserved word.
EDIT:
If you have a large amount of data, often it is faster to do the truncate/re-insert approach:
create table temp_t as
select t.*
from yourtable t join
(select title, `desc`, max(view) as maxview
from yourtable t
group by title, `desc`
) tt
on t.title = tt.title and
t.`desc` = tt.`desc` and
t.view = tt.maxview;
truncate table yourtable;
insert into yourtable
select *
from temp_t;
I could not understand what the specific question is. The possible solutions are followed...
1) Use UPDATE instead of INSERT statement in mysql. Just write UPDATE your_table_name SET view=view+1
2) or you can run a cron job if using php to delete duplicate rows having lower value
3) If INSERT is necessary then you should do ON DUPLICATE KEY UPDATE. Refer to the documentation * http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html