data ordering issue in mysql for a particular column - mysql

I have a table in which there is column name as mappedcloumnname and fieldname and my fieldcolumn contains address1, address2, city, state, customerid, country and mappedcolumn contanins c1-c20. I wrote a query to sort my data based on mappedcolumn name but the order what am getting is wrong one
SELECT * FROM customermetadata
WHERE OrgID = in_orgid
ORDER BY MappedColumnName;

You can give it a try:
SELECT
*
FROM
customermetadata
WHERE
OrgID = in_orgid
ORDER BY CAST(SUBSTRING(MappedColumnName FROM 2) AS UNSIGNED);
Note:
Here I've extracted the number from the MappedColumnName and sort the records based the extracted numbers.
I've created a demo where the table contains only two columns (id and col).
col column contains value like c1,c2,....
See demo if you order by col only.
See demo if you order by extracting number from col.

If your column MappedColumnName contains value from c1-c20, then it will be treated as String(VarChar) in SQL and data will not be sorted properly.

You should try in this way,
select * from customermetadata
where OrgID=in_orgid
Order By CAST(SUBSTR(MappedColumnName FROM 2 FOR LENGTH(MappedColumnName)) AS UNSIGNED); ;
NOTE: A longer number is also a bigger number for numbers of the same length, you can make a textual comparison, because '0' < '1' .... < '9' and it will short Alpha-numeric order.

Related

sort the json array in postgresql

create table sort(authorized json);
insert into sort values('{"name":"Authorized","states":[{"state_code":"CT","state_name":"Connecticut","is_checked":false},{"state_code":"NJ","state_name":"New Jersey","is_checked":false},{"state_code":"SC","state_name":"South Carolina","is_checked":false},{"state_code":"FL","state_name":"Florida","is_checked":false},{"state_code":"MT","state_name":"Montana","is_checked":false},{"state_code":"GA","state_name":"Georgia","is_checked":false},
{"state_code":"IA","state_name":"Iowa","is_checked":false},{"state_code":"AR","state_name":"Arkansas","is_checked":false},{"state_code":"UT","state_name":"Utah","is_checked":false},{"state_code":"ID","state_name":"Idaho","is_checked":false},{"state_code":"IL","state_name":"Illinois","is_checked":false},{"state_code":"IN","state_name":"Indiana","is_checked":false},{"state_code":"MA","state_name":"Massachusetts","is_checked":false},{"state_code":"MI","state_name":"Michigan","is_checked":false},{"state_code":"MS","state_name":"Mississippi","is_checked":false},{"state_code":"NM","state_name":"New Mexico","is_checked":false},{"state_code":"NV","state_name":"Nevada","is_checked":false},{"state_code":"RI","state_name":"Rhode Island","is_checked":false},{"state_code":"SD","state_name":"South Dakota","is_checked":false},{"state_code":"UT","state_name":"Utah","is_checked":false},{"state_code":"WV","state_name":"West Virginia","is_checked":false},{"state_code":"SD","state_name":"South Dakota","is_checked":false},
{"state_code":"WV","state_name":"West Virginia","is_checked":false}]}')
I want that this json sort according to state_code after update it looks like
{"name":"Authorized","states":[{"state_code":"AR","state_name":"Arkansas","is_checked":false},{"state_code":"CT","state_name":"Connecticut","is_checked":false},{"state_code":"FL","state_name":"Florida","is_checked":false},{"state_code":"GA","state_name":"Georgia","is_checked":false},
{"state_code":"IA","state_name":"Iowa","is_checked":false},{"state_code":"ID","state_name":"Idaho","is_checked":false},{"state_code":"IL","state_name":"Illinois","is_checked":false},{"state_code":"IN","state_name":"Indiana","is_checked":false},{"state_code":"MA","state_name":"Massachusetts","is_checked":false},{"state_code":"MI","state_name":"Michigan","is_checked":false},{"state_code":"MS","state_name":"Mississippi","is_checked":false},{"state_code":"MT","state_name":"Montana","is_checked":false},{"state_code":"NJ","state_name":"New Jersey","is_checked":false},{"state_code":"NM","state_name":"New Mexico","is_checked":false},{"state_code":"NV","state_name":"Nevada","is_checked":false},{"state_code":"RI","state_name":"Rhode Island","is_checked":false},{"state_code":"SC","state_name":"South Carolina","is_checked":false},{"state_code":"SD","state_name":"South Dakota","is_checked":false},{"state_code":"UT","state_name":"Utah","is_checked":false},{"state_code":"WV","state_name":"West Virginia","is_checked":false},{"state_code":"SD","state_name":"South Dakota","is_checked":false},{"state_code":"UT","state_name":"Utah","is_checked":false},
{"state_code":"WV","state_name":"West Virginia","is_checked":false}]}
try this:
select substr(column_name, position ('state_code":"' in column_name)+13,4) as stateCode
from table_name
order by stateCode asc/desc
note:the value 13 represents the lenght of field (state_code":) and 4 represents value of field ("AR")
might need to tweak a little according to you table and column. The select part would select your desired element then you only have to order it by asc or desc.
You can get the results ordered when retrieving the data through sorting within the subquery while extracting the concerned array(states) as a seperate column, and then aggregating the individual objects of the array back while adhering name element of the object such as
SELECT JSON_AGG(
JSON_BUILD_OBJECT( 'name', name, 'states', states)
) AS authorized
FROM
(
SELECT authorized->'name' AS name, j.states
FROM sort,
JSON_ARRAY_ELEMENTS(authorized->'states') AS j(states)
ORDER BY j.states->>'state_code' ) AS ns
Demo

SQL command for the last value. Additionally with a search ID

I would like to search my database via SQL command for the last value and for a given ID.
The ID works so well:
SELECT * FROM 'tem2' WHERE macid = '*'.
Unfortunately, if I add LAST ( SELECT LAST * FROM...) it does not work anymore.
SQL tables represent unordered sets. There is no "last" value unless a column specifies the ordering. Let me assume you have one.
Use order by and limit:
SELECT *
FROM tem2
WHERE macid = '*'
ORDER BY <ordering col>
LIMIT 1;
The ordering column would be a creation date or auto-incremented id.

mysql get max number from a string field

I need to get maximum number from a part of the value that generally start with year followed by slash(/). So I need a maximum number after the slash(/) but year should be 2016
2016/422
2016/423
2016/469
2016/0470
2014/777
2015/123
2015/989
I tried this query
SELECT columname FROM tablename WHERE columname LIKE '2016/%' ORDER BY id DESC
the above query always giving '2016/469' as first record, how to get '2016/0470' as the maximum number?
any help will be much appreciated.
Thank you.
If columname follows that pattern YEAR/0000, you can use SUBSTRING function from MySQL to remove the part of the string you don't want.
SELECT value FROM (
SELECT CAST(SUBSTRING(columname, 0, 4) AS UNSIGNED) as year, CAST(SUBSTRING(columname FROM 6) AS UNSIGNED) as value FROM tablename
) total
ORDER BY year DESC, value DESC
LIMIT 1;
You need to split the string into 2 parts and evaluate them as numbers, instead of strings. The following formula will return the number after the / in the fieldname. All functions used below are described in the string functions section of the MySQL documentation. This way you can get the number after the / character, even if it is not year before the /, but sg else. The + 0 converts the string to a number, eliminating any leading 0.
select right(columnname, char_length(columnname)-locate('/',columnname)) + 0
from tablename
Just take the max() of the above expression to get the expected results.
UPDATE:
If you need the original number and the result has to be restricted to a specific year, then you need to join back the results to the original table:
select columnname
from tablename t1
inner join (select max(right(t.columnname, char_length(t.columnname)-locate('/',t.columnname)) + 0) as max_num
from tablename t
where left(t.columnname,4)='2016'
) t2
on right(t1.columnname, char_length(1t.columnname)-locate('/',t1.columnname)) + 0 = t2.max_num
where left(t1.columnname,4)='2016'
There are lots of suggestions given as answers already. But some of those seem overkill to me.
Seems like the only change needed to the OP query is the expression in the ORDER BY clause.
Instead of:
ORDER BY id
We just need to order by the numeric value following the slash. And there are several approaches, several expressions, that will get that from the example data.
Since the query already includes a condition columname LIKE '2016/%'
We can get the characters after the first five characters, and then convert that string to a numeric value by adding zero.
ORDER BY SUBSTRING(columname,6) + 0 DESC
If we only want to return one row, add
LIMIT 1
http://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_substring
If we only want to return the numeric value, we could use the same expression in the SELECT list, in addition columnname.
This isn't the only approach. There are lots of other approaches that will work, and don't use SUBSTRING.
Try like this:
SELECT
MAX(CAST(SUBSTRING(t.name,
LOCATE('/', t.name) + 1)
AS UNSIGNED)) AS max_value
FROM
tablename AS t;
You can try with this little uggly approach:
SELECT t.id, t2.secondNumber FROM table AS t
JOIN (SELECT id,
CONCAT(SUBSTRING(field,1,5),
if(SUBSTRING(SUBSTRING(field, 6),1,1)='0',
SUBSTRING(field, 6),
SUBSTRING(field,7)
)
) as secondNumber FROM table ) AS t2 ON t2.id=t.id
ORDER BY t2.secondNumber DESC
Would be valid only if the 0 (zeroes) before the second number (after the slash) are no more than 1.
Or if the year doesn`t matter you can try to order them only by the second number if it is ok:
SELECT t.id, t2.secondNumber FROM table AS t
JOIN (SELECT id,
if(SUBSTRING(SUBSTRING(field, 6),1,1)='0',
SUBSTRING(field, 6),
SUBSTRING(field,7)
) as secondNumber FROM table ) AS t2 ON t2.id=t.id
ORDER BY t2.secondNumber DESC

Insert ID in column with values separated by comma

I have a column that lists all the units ids from a company which are allowed to see a specific document.
Like this:
And those ids are selected here ('Selecionar todas' mean 'Select All'):
The problem is when I add a new Unit, it come unselected and it will be a headache to have to enter in all of the documents that are supposed to show to all units and change it to be selected.
Is there a way to insert the new Unit's id into the 'idsunidades' column where there are all the other units selected ?
Sorry for the bad English.
To implement a select all option you should use a flag column all_selected(true or false) or you can do it like this:
To select the rows where All units are selected should have the longest value of idsunidades, you can select them like this
SELECT #maxLength:=LENGTH(idsunidades)
ORDER BY LENGTH(idsunidades )
DESC LIMIT 1
You can use CONCAT() to append the new id to the old column data
To add the unit 99 to the column idsunidades to all the rows with all units you can do this
UPDATE table set idsunidades=CONCAT(idsunidades, ',99')
WHERE LENGTH(idsunidades) = (SELECT LENGTH(idsunidades)
ORDER BY LENGTH(idsunidades )
DESC LIMIT 1)

SELECT in mysql using column number instead of name

Is there any way to do something like :
SELECT * FROM TABLE WHERE COLUMN_NUMBER = 1;
?
No, you can't. Column order doesn't really matter in MySQL. See the below question for more details.
mysql - selecting values from a table given column number
If your table has a column named COLUMN_NUMBER and you want to retrieve rows from the table where that column contains a value of '1', that query should do the trick.
I suspect that what you are trying to do is reference an expression in the select list with an alias. And that is not supported. An expression in the WHERE clause that references a column must reference the column by name.
We can play some tricks with inline views, to give an alias to an expression, but this is not efficient in terms of WHERE predicates, because of the way MySQL materializes a derived table. And, in that case, its a name given to the column in the inline view that has to be referenced in the outer query.
How I did it:
I'm trying to take (last 3 values of) column number 4 in sometable.
set #mydb=(SELECT DATABASE());
set #mycol=(select COLUMN_NAME from information_schema.columns where
table_schema=#mydb and table_name='sometable' and ordinal_position = 4);
SELECT Date,#mycol FROM sometable ORDER BY Date DESC LIMIT 3;
Of course, if Database name is known, first line could by whiped and #mydb replaced by real database name.
You can do this trick
Example:
$query="select * from employee";
$result=mysql_query($query);
$meta=mysql_fetch_field($result,0) // 0 is first field in table , 1 is second one ,,, etc
$theNameofFirstField=$meta->name; // this well return first field name in table
// now you can use it in other query
$seconQuery="select $theNameofFirstField from employee";