Count Characters after a certain pattern - mysql

I have a database that contains a column "Code" where the records have the following format "xx-xxx" and "xx-xx", for the later format i want to add a zero after the "-" to make it "xx-0xx", is there anyway to count the characters after a certain pattern in Mysql

Hmmm. If those are your only two possibilities, you can use case:
select (case when length(code) = 5
then replace(code, '-', '-0')
else code
end) as new_code
If you want to be more general, deconstruct the string and build it back again:
select concat_ws('-', substring_index(code, '-', 1),
lpad(substring_index(code, '-', -1), 3, '0')
)

Yes, you can use the CHAR_LENGTH(str) like this:
SELECT code,CHAR_LENGTH(SUBSTR(code,3))
from table

Related

GROUP BY multiple text matches within one column

Given data like:
URL
some_url.com
some_url.com
some_url.co.uk
some_other_url.com
some_other_url.co.uk
some_other_url.co.uk
some_other_url.org
is there a way to construct a query that will result in;
some_url 3
some_other_url 4
Currently I'm either using a standard group by url or I query the aggregations one by one using LIKE
Is there a way to do this in one query? (using mysql currently, but will be moving this data over to postgresql)
Would it be better practice to add a column to reflect this grouping (at insert time)? (this feels redundant but would be best performing I guess)
EDIT:
data can contain www and non-www as well as http, https. Also I'll have to do similar thing on other columns that contain (free) text values.
This is ANSI SQL compliant and should probably work with both MySQL and Postgresql:
select url, count(*)
from
(
select substring(url from 1 for position('.' in url) -1) as url
from tablename
) dt
group by url
Using position() to find the first . character. Do substring() and finally GROUP BY the result.
use SUBSTRING_INDEX in mysql which help you substring from a string before a specified number of occurrences of the delimiter.
select count(*) as cnt, SUBSTRING_INDEX(c,'.',1) as val from cte
group by SUBSTRING_INDEX(c,'.',1)
Since the values can have http, https and www, and may be query string too, you will have to clean all such values first before grouping it. Took the reference from here and modified it to match your requirement.
SELECT url,
SUBSTRING_INDEX(
SUBSTRING_INDEX(
SUBSTRING_INDEX(
SUBSTRING_INDEX(
SUBSTRING_INDEX(
SUBSTRING_INDEX(url, '/', 3),
'://', -1),
'/', 1),
'?', 1),
'www.', -1),
'.', 1) AS domain,
COUNT(1)
FROM tblname
GROUP BY domain;
This works in Postgesql:
select split_part(url,'.',1) g,count(*)
from url_table
group by g
order by g;
Best regards,
Bjarni

How to treat same ALIKE enteries in database as one in Group By

I am trying to wite a Mysql query to group all the same entries in database as one.I have a data base with different colors name , entries in database are like
Contract Color
OG-46374 I.Khaki
OG-46375 I-KHAKI
OG-46376 I KHAKI
OG-46377 W Ocher
OG-46378 W.Ocher
Now the problem is my database in treating all these values as different entries whereas i cant handle or force the operator to write the exact values how can I treat all "I Khaki" and W ocher color as one not different colors in group by clause
My Sql query is somehow like
SELECT
*,
ROUND(SUM(meter_yard_length), 0) AS TotaL_Length_Contract,
ROUND(SUM(IF(quality = 'A', meter_yard_length, 0)),
0) AS A_Quality_length,
ROUND(SUM(IF(quality = 'B', meter_yard_length, 0)),
0) AS B_Quality_length GROUP BY r.contract_no, r.color DESC;
Kindly tell the generic solution because i have many possibilities like "I*khaki" "I--Khaki" etc i cant control all of them through replace etc
This answer is based on the very limited sample data you provided. I see two problems with color names. First, not all letters are in the same case always. And second, there maybe be, in a given position, either a space, period, or dash, when in fact all three represent the same logical name. We can try using REPLACE to convert the dots and dashes into space, then use LOWER() to handle the case issue.
SELECT
contract_no,
LOWER(REPLACE(REPLACE(color, '.', ' '), '-', ' '))
ROUND(SUM(meter_yard_length), 0) AS TotaL_Length_Contract,
ROUND(SUM(IF(quality = 'A', meter_yard_length, 0)),
0) AS A_Quality_length,
ROUND(SUM(IF(quality = 'B', meter_yard_length, 0)),
0) AS B_Quality_length
FROM yourTable
GROUP BY
contract_no,
LOWER(REPLACE(REPLACE(color, '.', ' '), '-', ' '));
Demo

How to extract part of a Base64 encoded string in MySQL?

I have a field in my database which is encoded. After using from_base64 on the field it looks like this:
<string>//<string>//<string>/2017//06//21//<string>//file.txt
There may be an undetermined number of strings at the beginning of the path, however, the date (YYYY//MM//DD) will always have two fields to the right (a string followed by file extension).
I want to sort by this YYYY//MM//DD pattern and get a count for all paths with this date.
So basically I want to do this:
select '<YYYY//MM//DD portion of decoded_path>', count(*) from table group by '<YYYY//MM//DD portion of decoded_path>' order by '<YYYY//MM//DD portion of decoded_path>';
Summary
MySQL's SUBSTRING_INDEX comes in useful for doing this by looking for the specified delimiter and counting backwards from the end if a negative count value is specified.
Demo
Rextester demo: http://rextester.com/TCJ65469
SQL
SELECT datepart,
COUNT(*) AS occurrences
FROM
(SELECT CONCAT(
LEFT(SUBSTRING_INDEX(txt, '//', -5), INSTR(SUBSTRING_INDEX(txt, '//', -5), '//') - 1),
'/',
LEFT(SUBSTRING_INDEX(txt, '//', -4), INSTR(SUBSTRING_INDEX(txt, '//', -4), '//') - 1),
'/',
LEFT(SUBSTRING_INDEX(txt, '//', -3), INSTR(SUBSTRING_INDEX(txt, '//', -3), '//') - 1))
AS datepart
FROM tbl) subq
GROUP BY datepart
ORDER BY datepart;
Assumptions
Have assumed for now that the single slash before the year in the example given in the question was a typo and should have been a double slash. (If it turns out this isn't the case I'll update my answer.)
little crazy but it works
select REPLACE(SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE('<string>//<string>//<string>/2017//06//21//<string>//file.txt',"//","-"),"/",-1),"-<",1),"-","/"), count(*) from `chaissilist` group by REPLACE(SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE('<string>//<string>//<string>/2017//06//21//<string>//file.txt',"//","-"),"/",-1),"-<",1),"-","/") order by REPLACE(SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE('<string>//<string>//<string>/2017//06//21//<string>//file.txt',"//","-"),"/",-1),"-<",1),"-","/");

is there anyway to count values in a set of mysql cloumn

How can I get the number of values specified in a MySQL SET column?
Is there any built function in mysql ?
SELECT id, LENGTH(colname) - LENGTH(REPLACE(colname, ',', '')) + 1 AS set_count
FROM YourTable
This answer:
https://stackoverflow.com/a/10738323/1176436
Assuming you don't have values like '123,123,' (note the comma at the end) this should work:
SELECT
LENGTH(yourColumn) - LENGTH(REPLACE(yourColumn, ',', '')) + 1 AS numberOfItemsInRow
FROM yourTable;
Find more information here.
But it would really be better to normalize your database!

I would like to replace the text in a column from "300-21-2" to "300-21-02" with one query

Is there an easy way to replace all the text in a VARCHAR 255 column from "300-21-2" to "300-21-02" with one query?
Thank you.
This is basic SQL
UPDATE tablename
SET columnname = '300-21-02'
WHERE columnname = '300-21-2'
If the pattern is always the same NNN-NN-N then what you need is:
update tablex
set column = concat( substr(column,1,7), lpad(substr(column,8),2,'0') )
see it at fiddle:
http://sqlfiddle.com/#!2/f59fe/1
EDIT As the op showed the pattern
update tablex
set column = CONCAT(
substring_index(col, '-',1), '-',
lpad(substring_index(substring_index(col, '-',-2), '-', 1),2,'0'), '-',
lpad(substring_index(col, '-',-1), 2, '0') )
If you like to convert the first set like 300 to 00300 as your pattern you add the lpad as this: lpad(substring_index(col, '-',1),5,'0')
This should be a lot easier if mysql has support to regex replace, but as it hasnt you have to work with the strings:
from this value: '300-02-1'
from substring_index(col, '-',1) I'm getting: 300
from substring_index(substring_index(col, '-',-2), '-', 1) I'm getting 02 I did this because just put the substring_index(col, '-',2) gave me 300-02 so, i got it from right to left (-2) then i get the first
and substring_index(col, '-',-1) it bring me 1 because it gets the value from right to left
Then I just concatenate it all formatting the ones I want.