Ordering by inches value in MYSQL - mysql

I've searched for the answer to this but can't quite work it out. I think I'm close but need your help please.
I have the following mysql query:
SELECT `size`
FROM `table`
GROUP BY `size`
ORDER BY CONVERT(SUBSTR(size, 1, POSITION('/' IN size) - 1), UNSIGNED INTEGER) ASC,
SUBSTRING_INDEX(size,'/',1)/SUBSTRING_INDEX(size,'/',-1) ASC
Running this gives the following result:
1"
2"
4"
3"
1/2"
3/8"
3/4"
11/4"
11/2"
21/2"
I need the sizes to come out smallest to largest. Any help on this would be massively appreciated. Thank you.
Note, I have also tried removing the " from the sizes in the database and the result was exactly the same.
An example of the dataset:
1 1/2"
1 1/4"
1"
1/2"
1/4"
1/8"
10"
11/2"
11/4"
11/4""
12"
14"
16"
2 1/2"
2"
21/2"
3"
3/4"
3/8"
4"
5"
6"
8"

Lovely data format. I think you are going to have to do the division. The calculation is something like this:
order by (case when size like '%/%'
then (substring_index(size, '/', 1) + 0) / (substring_index(size, '/', 2) + 0)
else size + 0
end)
Even if the " is part of the field, this will still work. The + 0 does "silent" conversion. That is, it converts the string up to the first non-numeric character.
EDIT:
If you could have spaces with whole numbers first, you would do:
order by (case when size like '% %/%'
then (substring_index(size, 1, ' ') + 0) +
((substring_index(substring_index(size, ' ', 2), '/', 1) + 0) /
(substring_index(size, '/', -1) + 0)
)
when size like '%/%'
then (substring_index(size, '/', 1) + 0) / (substring_index(size, '/', 2) + 0)
else size + 0
end)

You query almost work. However in first part of the order by you should substract the position from the string length.
SELECT `size`
FROM `size`
GROUP BY `size`
ORDER BY CONVERT(SUBSTR(size, 1, LENGTH(size) - POSITION('/' IN size) - 1), UNSIGNED INTEGER) ASC,
SUBSTRING_INDEX(size,'/',1)/SUBSTRING_INDEX(size,'/',-1) ASC
http://sqlfiddle.com/#!2/cd0658/6

Related

How To Substring and Add a Range

I have an URL that needs to be shortened. I have 2 formats of the URL, first one is /item/10/0100-, it stops at first -, the second one is /item/12/0100-CAK, it needs 3 more characters after the -.
Below is the example,
/item/10/0100-NAU1X010-10-A032 need to be /item/10/0100-
/item/2/0888-ADBACS11101-2-A048 need to be /item/2/0888-
/item/12/0100-CAK101827812018101-12-A034 need to be /item/12/0100-CAK
/item/3/0110-MSS0016-T03-3-A034 need to be /item/3/0110-MSS
I already try this query
CASE
WHEN Page LIKE "/item/10%" OR Page LIKE "/item/2/%" THEN CONCAT(SUBSTRING_INDEX(SUBSTR(Page, LOCATE('/', Page)+1), '-', 1), "-")
WHEN Page LIKE "/item/12%" OR Page LIKE "/item/3/%" THEN SUBSTRING_INDEX(SUBSTR(Page, LOCATE('/', Page)+1), '-', 1) + 4
ELSE Page
END
But it doesn't give me the right result. It seems simple but I really can't get over it. Please help me with this problem, thank you.
Use string functions in the CASE expression like this:
SELECT
page,
CASE
WHEN Page LIKE '/item/10%' OR Page LIKE '/item/2/%' THEN
CONCAT(SUBSTRING_INDEX(Page, '-', 1), '-')
WHEN Page LIKE '/item/12%' OR Page LIKE '/item/3/%' THEN
CONCAT(SUBSTRING_INDEX(Page, '-', 1), SUBSTR(Page, LOCATE('-', Page), 4))
ELSE Page
END short_Page
FROM tablename
See the demo.
Results:
> page | short_Page
> :--------------------------------------- | :----------------
> /item/10/0100-NAU1X010-10-A032 | /item/10/0100-
> /item/2/0888-ADBACS11101-2-A048 | /item/2/0888-
> /item/12/0100-CAK101827812018101-12-A034 | /item/12/0100-CAK
> /item/3/0110-MSS0016-T03-3-A034 | /item/3/0110-MSS
SELECT Path,
SUBSTRING(Path FROM 1 FOR LOCATE('-', Path) + 3 * (#format = 2)) AS shortened
FROM test;
The format is differentiated by the number after /item/
SELECT Path,
SUBSTRING(Path FROM 1 FOR LOCATE('-', Path) + 3 * (SUBSTRING_INDEX(SUBSTRING_INDEX(Path, '/', 3), '/', -1) IN (12, 3))) AS shortened,
(SUBSTRING_INDEX(SUBSTRING_INDEX(Path, '/', 3), '/', -1) IN (12, 3)) + 1 used_format
FROM test;
Adjust the values list for format 2.
fiddle

How to auto increment a string with sql query

I am stuck at a point where i have to increment a string, and my strings are of type C001,SC001,B001
in my data base they are defined like
what i am trying to do do is write a query which check the previous highest code present into my db and the incriment it to +1
for example C001 -> C002,C009->C010,C099`->C100 and so on
Similarly for SC001->SC002,SC009->SC010,SC099->SC100 and so on
Similarly fro B001 -> B002,B009->B010,B099`->B100 and so on
I have a query which my friend has suggested me to use but that query only incriminating AAAA->AAAA01 , AAAA09->AAAA10
query is
SELECT id AS PrevID, CONCAT(
SUBSTRING(id, 1, 4),
IF(CAST(SUBSTRING(id, 5) AS UNSIGNED) <= 9, '0', ''),
CAST(SUBSTRING(id, 5) AS UNSIGNED) + 1
) AS NextID
FROM (
-- since you allow strings such as AAAA20 and AAAA100 you can no longer use MAX
SELECT id
FROM t
ORDER BY SUBSTRING(id, 1, 4) DESC, CAST(SUBSTRING(id, 5) AS UNSIGNED) DESC
LIMIT 1
) x
when i am replacing ID with CategoryCode it is giving me PrevID-C004 NextID-C00401 which is not my requirement i want PrevID-C004 and NextID->C005
NOTE i am using my sqlServer 5.1
Just try this one ,
SELECT
CategoryCode,CAST(CONCAT(LPAD(CategoryCode,1,0),LPAD(MAX(RIGHT(CategoryCode,
3)) + 1, 3, 0) ) AS CHAR),
FROM test
SELECT
SubCategoryCode,CAST(CONCAT(LPAD(SubCategoryCode,2,0),
LPAD(MAX(RIGHT(CategoryCode, 3)) + 1, 3, 0) ) AS CHAR),
FROM test
SELECT
BrandCode,CAST(CONCAT(LPAD(BrandCode,1,0), LPAD(MAX(RIGHT(BrandCode, 3)) +
1, 3, 0)) AS CHAR) FROM test

cast(SUBSTRING with decimal

I have this line that works and gets my column into a number
case when Auth_Amt LIKE '%DAY%' then cast(SUBSTRING(Auth_Amt FROM 1 FOR POSITION('/DAY' IN Auth_Amt) - 1) as numeric) when Auth_Amt LIKE '%TAX%' then cast(SUBSTRING(Auth_Amt FROM 1 FOR POSITION(' ' IN Auth_Amt) - 1) as numeric)
when Auth_Amt LIKE '%SCHG%' then cast(SUBSTRING(Auth_Amt FROM 1 FOR POSITION(' ' IN Auth_Amt) - 1) as numeric)
else 0
end as Amt_Day
what can I add to this to make it come back with two decimal spots also. Right now it is whole numbers bring back.
You can try like this:
case when Auth_Amt LIKE '%DAY%' then CAST(cast(SUBSTRING(Auth_Amt FROM 1 FOR POSITION('/DAY' IN Auth_Amt) - 1) as decimal(13,2)) as decimal(13,2))
when Auth_Amt LIKE '%TAX%' then CAST(cast(SUBSTRING(Auth_Amt FROM 1 FOR POSITION(' ' IN Auth_Amt) - 1) as decimal(13,2)) as decimal(13,2))
when Auth_Amt LIKE '%SCHG%' then CAST(cast(SUBSTRING(Auth_Amt FROM 1 FOR POSITION(' ' IN Auth_Amt) - 1) as decimal(13,2)) as decimal(13,2))
else 0
end as Amt_Day
In general you have to CAST it like this:
CAST(yourField as decimal(13,2))

MySQL convert height format to centimeters

I want to convert feet and inches to centimeters format
Format in my DB is:
4'6" (4 feet, 6 inches)
Formula for converting into centimeters
4*30.48 = 121.92 (convert feet to centimeters = multiply by 30.48)
6*2.54 = 15.24 (convert inches to centimeters = multiply by 2.54)
So Result = 121.92 + 15.24 = 137.16 cm
eg:
Actual Table: inches
SELECT * FROM inches
id height
1 4'6"
2 4'7"
3 5'8"
4 5'9"
I expect the following result as centimeters when I do SQL query
id height
1 137.16
2 139.7
3 172.72
4 175.26
Thanks in advance :)
Probably far easier to do on the application level, but if you really had to, you could do it in SQL like this, using the SUBSTR and INSTR functions, and some basic math:
SET #height = '4''6"';
SELECT
SUBSTR(#height, 1, INSTR(#height, '''') - 1) * 12 * 2.54 +
SUBSTR(#height, INSTR(#height, '''') + 1, INSTR(#height, '"') - INSTR(#height, '''') - 1) * 2.54;
-- yields 137.16
Or, applied to your table structure:
SELECT id,
SUBSTR(height, 1, INSTR(height, '''') - 1) * 12 * 2.54 +
SUBSTR(height, INSTR(height, '''') + 1, INSTR(height, '"') - INSTR(height, '''') - 1) * 2.54 AS height
FROM inches;
Application side process will be better,
However,
SELECT
(CAST(SUBSTR(height,1, LOCATE("'",height)-1) AS UNSIGNED) * 30.48) +
(CAST(SUBSTR(height, LOCATE("'",height)+1) AS UNSIGNED) * 2.54 ) AS cm
FROM
inches;

Calculate average of some columns, not counting null values

I have a table with some readings that looks like this:
id foo bar baz qux
1 2 4 NULL 3
2 6 11 0 2
I want to calculate an average of some columns, not including null values in the count. Something like this pseudo-code:
select (foo+bar+baz)/countNonNulls(foo,bar,baz) AS result
FROM readings WHERE id=1;
I.e, my expected result is (2+4)/2 = 3.
Is there a way to do this in a single SQL query?
In MySQL, you can use:
select (coalesce(foo, 0) + coalesce(bar, 0) + coalesce(baz, 0) /
((foo is not null) + (bar is not null) + (baz is not null))
) as average
Note that this assumes that at least one value is not null, to prevent division by 0.
To handle the general case, you can use case:
select (case when coalesce(foo, bar, bz) is not null
then (coalesce(foo, 0) + coalesce(bar, 0) + coalesce(baz, 0) /
((foo is not null) + (bar is not null) + (baz is not null))
)
end) as average
try the where clause: where [nameColumn] is not null