count of distincts substring in query - mysql

I'm trying to create a query that count (or at least retrieve) distincts occurrences of a substring in a column.
I have one column that is like this:
elem1=value1|elem2=value2|elem3=value3
I want to retrieve distincts values of elem2 and the number of ocurrences.
SELECT
substring(
column , LOCATE( 'elem2=' , column ) + $1 , $2
) AS a ,
COUNT(*) b ,
FROM
column ORDER BY a;
Thanks

Here's one way to achieve the specified result.
SELECT COUNT(DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(t.col,'elem2=',-1),'|',1))
FROM t
WHERE t.col LIKE '%elem2=%'
Apparently, I misread the question (the query above returns a count of distinct values. Or, I just lost track of the specified result, while I was working on the tedious string parsing.
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(t.col,'elem2=',-1),'|',1) AS a
, COUNT(*) AS b
FROM t
WHERE t.col LIKE '%elem2=%'
GROUP BY SUBSTRING_INDEX(SUBSTRING_INDEX(t.col,'elem2=',-1),'|',1)
ORDER BY SUBSTRING_INDEX(SUBSTRING_INDEX(t.col,'elem2=',-1),'|',1)
NOTE:
Note that SQL wasn't really designed for parsing values out of strings.
The normative relational pattern for this type of data would to create a table, with columns named elem1, elem2, elem3, and to store each separate value in a column.
For example:
CREATE TABLE t
( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY
, elem1 VARCHAR(80)
, elem2 VARCHAR(80)
, elem3 VARCHAR(80)
);
INSERT INTO t (elem1, elem2, elem3) VALUES ('value1', 'value2', 'value3');
To get a count of distinct values in elem2 column, we'd do something like this.
SELECT COUNT(DISTINCT elem2)
FROM t
To get the distinct values of elem2 along with the count of occurrences
SELECT elem2 AS a
, COUNT(*) AS b
FROM t
GROUP BY elem2
ORDER BY elem2
That's essentially the same as the query at the beginning of my answer; the first query just has to do the parsing the 'elem2=value2' out of the string.

Related

How to sort the string on the basis of numbers?

I am working on the sql query in which I want to sort the string on the basis of numbers.
I have one column (Column Name is Name) table in which there are multiple fields. On using ORDER BY NAME, it prints in the following way:
hello_world
hello_world10
hello_world11
hello_world12
hello_world13
hello_world14
hello_world15
hello_world4
hello_world5
For the above query, I have used ORDER BY NAME; but it doesn't seem to print on the basis of numbers.
Problem Statement:
I am wondering what sql query I need to write or what changes I need to make in my sql query above so that it prints everything on the basis of numbers, the o/p should be this:
hello_world
hello_world4
hello_world5
hello_world10
hello_world11
hello_world12
hello_world13
hello_world14
hello_world15
you want a numeric ordering, then you need to create a numeric value to order on.
currently you have strings.
if the pattern is true, then you can use a combination of string manipulation to trim off the first characters, which should leave only numbers, then use TO_NUMBER() to convert for the ordering
something like
select name
from mytable
order by to_number( replace( name, 'hello_world','' ))
I think the simplest solution for this particular case (where all the values have the same prefix) is:
order by length(name), name
Try this:
SELECT name,
CASE WHEN REGEXP_INSTR(name, '[0-9]') = 0 THEN 0
ELSE CAST(SUBSTR(name, REGEXP_INSTR(name, '[0-9]')) AS INT)
END AS progressive
FROM my_table
ORDER BY progressive;
we can order it using replace and cast methods.
I tried the following query
select Name, cast(REPLACE(Name, 'hello_world', '') as UNSIGNED ) as repl from Users order by repl;
To generage sample data
CREATE TABLE Users (
Name varchar(255) NOT NULL
);
insert into Users(Name) values
('hello_world'),
('hello_world4'),
('hello_world5'),
('hello_world10'),
('hello_world11'),
('hello_world12'),
('hello_world13'),
('hello_world14'),
('hello_world15')
;
EDIT
query without replaced column,
select City from Persons order by cast(REPLACE(City, 'hello_world', '') as UNSIGNED );
Though the question is about mysql.
I tried in sql server.
create table #t1 (id varchar(100));
insert into #t1 (id) values ('Pq1'),('pq3'),('pq2')
select * from #t
order by
CAST(SUBSTRING(id + '0', PATINDEX('%[0-9]%', id + '0'), LEN(id + '0')) AS INT)

MySQL How to split string from column by " " and insert result separated by , into another column?

I would like to ask how to split string from column (all rows in table) by " " and insert result separated by , into another column in same table?
Many thanks for any advice.
Table struct example:
------------------------------------------
| Original string | Spliced string |
------------------------------------------
| Some string 001 | Some,String,001 |
------------------------------------------
If I needed to "split" a string on a delimiter, I'd likely make use of the nifty SUBSTRING_INDEX function. But there are a few quirks to be aware of.
The approach I would take would certainly be to write a SELECT statement first. That would include the expression(s) in the SELECT list that return the "separated" values that I wanted to assign to another column. I'd get those expressions tested using a SELECT statement, before I wrote an UPDATE statement.
SELECT t.id
, t.column_i_want_to_split
, expr1
FROM mytable t
ORDER BY t.id
To test specific cases, I'd make use of an inline view
SELECT t.id
, t.note
, t.val
, expr1
FROM ( SELECT 1 AS id, 'empty string test' AS note, '' AS val
UNION ALL SELECT 2, 'null', NULL
UNION ALL SELECT 3, 'one space', ' '
UNION ALL SELECT 4, 'four spaces', ' '
UNION ALL SELECT 5, 'test5', ' abc def '
UNION ALL SELECT 6, 'test6', 'g hi kl m'
) t
ORDER BY t.id
Once I had the expression(s) returning the values I want to assign to another column, I'd convert the SELECT into an UPDATE statement. To process all rows, omit the WHERE clause.
UPDATE mytable t
SET t.another_column = expr1
Without a more definitive specification, or at least some concrete examples of what you are attempting to achieve, we're just guessing. Given only a general description of the problem, all we can offer is some general advice.

UNION three different SELECTs in MYSQL

I have this MYSQL table named people with the columns: id|firstname|lastname|birthdate|phone.
I am quite new to MYSQL and I'm trying to UNION several SELECTs so that the result will look in the following way:
only the first 20 results must be shown
the first SELECT criteria is by the combination firstname+lastname+birthdate: WHERE (birthdate="1980-01-01") AND ((firstname LIKE "%john%") AND (lastname LIKE "%smith%"))
the second SELECT criteria is by the combination firstname+lastname: WHERE (firstname LIKE "%john%") AND (lastname LIKE "%smith%")
the third SELECT criteria is by phone: WHERE phone="0123456"
the output result must in fact have 3 columns: order|id|type; where "order" and "type" are alias columns
the exported ids must be unique: if the same id results from all the 3 SELECTs (or from more than one SELECT), then it must appear only once in the output table
the column "order" must have the value 1 for the results of the first SELECT, 2 for the 2nd SELECT and 3 for the last SELECT
if the same id value results from more than one SELECT, then its row must have the highest order value; where the highest order posible is 1, from the first SELECT
the alias column "type" must work like this: if an id results from the 1st SELECT, it's type value is "~firstname+lastname+birthdate~"; if an id results from the 2nd SELECT, it's type value is "~firstname+lastname~"; and finally if an id results from the 3rd SELECT, it's type value is "~phone~"
if the same id value results from more than one SELECT, the value on the "type" alias column must be a concatention between the SELECTs where that id was found (for example, if the same id resulted in all 3 SELECT queries then the value on the "type" column would be "~firstname+lastname+birthdate~~firstname+lastname~~phone~")
Is it possible to achieve such an output?
Here's something using CASE statements. I think you'll get into a mess with union statements, because of your order type statement. Hopefully I've understood what you're after - it's much easier if you post sample data! Anyway, even if this doesn't do exactly what you want, you get the idea....
[EDIT] I don't think you need the distinct, but I don't think it hurts, either...
SELECT DISTINCT
CASE WHEN birthdate='1980-01-01'
AND firstname LIKE '%john%' AND lastname LIKE '%smith%'
THEN 1
WHEN firstname LIKE '%john%' AND lastname LIKE '%smith%'
THEN 2
WHEN phone='0123456'
THEN 3
END AS outputorder, -- avoid confusion of using an SQL keyword as a column name,
id,
CONCAT(
CASE
WHEN birthdate='1980-01-01'
AND firstname LIKE '%john%' AND lastname LIKE '%smith%'
THEN CONCAT('~',firstname,'+',lastname,'+','~')
END ,
CASE WHEN firstname LIKE '%john%' AND lastname LIKE '%smith%'
THEN CONCAT('~',firstname,'+',lastname,'~')
END ,
CASE WHEN phone='0123456'
THEN CONCAT('~',phone,'~')
END
) -- end the concat
AS outputtype
FROM
mytable
WHERE
( birthdate='1980-01-01'
AND firstname LIKE '%john%' AND lastname LIKE '%smith%')
OR
(firstname LIKE '%john%' AND lastname LIKE '%smith%')
OR
phone='0123456'
ORDER by 1,2 LIMIT 20
In the end I did something like this and it worked just fine:
SELECT MIN(`ord`) AS `order` , `id` , GROUP_CONCAT(`spec`) as `type` FROM (
SELECT "1" AS `ord` , `id` , "~firstname+lastname+birthdate~" AS `spec` FROM `people` WHERE (`birthdate` = "1986-04-02") AND (`lastname` LIKE "%smith%") AND (`firstname` LIKE "%john%")
UNION
SELECT "2" AS `ord` , `id` , "~firstname+lastname~" AS `spec` FROM `people` WHERE (`lastname` LIKE "%smith%") AND (`firstname` LIKE "%john%")
UNION
SELECT "3" AS `ord` , `id` , "~phone~" AS `spec` FROM `people` WHERE (`phone`="0123456")
) final
GROUP BY final.`id`
ORDER BY `order` ASC
LIMIT 20
Thanks to mlinth for the alternative though...

Select row by using one distinct column

I have one table named dictionarydefinition.
CREATE TABLE dictionarydefinition (
id bigint NOT NULL,
definition character varying(1024) NOT NULL,
word character varying(200) NOT NULL,
grammertypename character varying(20) NOT NULL,
)
I have sql command Select * from dictionarydefinition where word like 'someword%'.
Results are multiple rows that got same value. For example if someword% is just empty ''
the result will be:
A
A
A
B
B
C
D
D
D
I just want result be:
A
B
C
D
I have used GROUP BY command, but it takes too much time to process 30MB database for my android device.
What kind of SQL commands I can add to make it choose only one row which got someword% value?
For the example you have mentioned, you can use GROUP BY.. Suppose the column-name for the alphabets is word, the command would be :
SELECT * from dictionarydefinition where word like 'someword%' GROUP BY word;
You can use SELECT TOP or LIMIT or ROWNUM
SELECT TOP 1 * from dictionarydefinition where word like 'someword%';
or
SELECT * from dictionarydefinition where word like 'someword%' LIMIT 1;
or
SELECT * from dictionarydefinition where word like 'someword%' AND ROWNUM <= 3

How do you select from mysql where last character in a string = x?

I'd like to select rows from the database where the last character in the mov_id column equals to 1 and 2.
How would the query look like?
SELECT * FROM `myTable` WHERE `mov_id` LIKE '%1' OR `mov_id` LIKE '%2'
the % character is a wildcard which matches anything (like * in many other places)
If mov_id is a numeric value (TINYINT, INT, etc...) then you should use a numeric operator. For instance, use the modulo operator to keep the last digit
SELECT * FROM mytable
WHERE (mov_id MOD 10) IN (1, 2)
If mov_id is a string, you can use LIKE or SUBSTRING(). SUBSTRING() will be slightly faster.
SELECT * FROM mytable
WHERE SUBSTRING(mov_id, -1) IN ('1', '2')
If your table is big or that query is frequently run, you should definitely consider adding a column to your table, in which you would store mov_id's last digit/character, and index that column.
Try this way too:
SELECT field1
FROM table
WHERE RIGHT(field1, 1) = 'x'
it displays the fields that has last a value of x.
SELECT *
FROM Table
WHERE RIGHT(Column_name, 1) IN ('x')
if you want to match two character just replace 1 by 2.
In general:
RIGHT(COLUMN_NAME, NO_OF_CHARACTER_YOU WANT_TO_MATCH_FROM_LAST)
And if you want to match the starting char just use LEFT instead of RIGHT
You could also do something like:
select
your, fields, go, here
from table
where
substring(mov_id, (char_length(move_id) - 1)) = x
SELECT * FROM table WHERE mov_id REGEXP '1$' OR mov_id REGEXP '2$'