Use of right string function [duplicate] - mysql

This question already has answers here:
Any way to select from MySQL table where a field ends in certain character/number?
(7 answers)
Closed 7 years ago.
I need to list a few details from a certain table, where two columns end with a certain number, and I must use the RIGHT string function.
Using MySQL Workbench
So far I have:
Select dog_id, Cat_id, Place
FROM EVENT_ENTRY
In the columns dog_id and cat_id, there is data such as 501, 502, 401, 301, 201, 101, 91 etc.
I need to list all of the data from both dog_id and cat_id that ends with 1, using the right string function.
Any help would be greatly appreciated. Cheers.

SELECT dog_id, Cat_id, Place FROM EVENT_ENTRY
WHERE RIGHT(dog_id, LEN(dog_id)) = 1 AND RIGHT(cat_id, LEN(cat_id))

SELECT dog_id, Cat_id, Place
FROM EVENT_ENTRY
WHERE RIGHT(dog_id,1)='1' and RIGHT(cat_id,1)='1';

If these are int columns (or any other integer data type for that matter), it's better to test if modulu 2 = 1, like this: WHERE Dog_Id % 2 = 1 AND Cat_Id % 2 = 1
If these are string columns (nchar, nvarchar etc.), you can use the right function, like this: WHERE RIGHT(Dog_Id, 1) = '1' AND RIGHT(Cat_Id, 1) = '1',
or use like with a wildcard, like this: WHERE Dog_Id LIKE '%1' AND Cat_Id LIKE '%1'

Related

Is it possible to do "reverse" prefix search

I have a table with these columns:
id
name
1
a
2
a.b
3
a.b.c
4
a.b.c.d
5
d
6
d.e
7
d.e.f
If I run query:
SELECT id FROM table WHERE name LIKE 'a%'
I can get 1, 2, 3 and 4. However, is it possible to do the reverse, such as:
SELECT id FROM table WHERE prefix_match(name, 'a.b.c')
which will return 1, 2, 3, but not 4.
Does MySQL have such prefix_match logic?
Try this:
SELECT id FROM table WHERE 'a.b.c' LIKE concat(name, '%')
See it work here:
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=484dc7c4acee09de5129c4ebe1b47edf
SELECT id FROM `names` WHERE SUBSTR('a.b.c', 1, LENGTH(name)) = name
This will select all the IDs whose corresponding name begins with a substring of 'a.b.c', but only for names that are not longer than 'a.b.c' (5 chars).

How to count the length of column seperated by ',' after using group_concat [duplicate]

This question already has answers here:
How to count items in comma separated list MySQL
(6 answers)
Closed 3 years ago.
I have a table looks like below:
ID path
| 1 YouTube,Newsletter,Social
| 2 YouTube,Newsletter
| 3 YouTube
Now I want to create a column to count the length of the path column. such as below:
ID path count weights
| 1 YouTube,Newsletter,Social 3 0.33
| 2 YouTube,Newsletter 2 0.5
| 3 YouTube 1 1
How do I do this?
I have tried JSON_LENGTH but couldn't get the command working.
PS. essentially I'm trying to replicate a query in PostgreSQL:
' select user_id, channels, 1.0 / array_length(channels, 1) as weights
from (
// ... query for marketing_channels as before)'
I am using MYSQL.
select d.email_entry_id
,d.channels
,JSON_LENGTH(d.channels)
from (
select email_entry_id
,group_concat(attribution_string order by visit_date asc separator ',' ) as channels
from database) d
error message: Error Code: 1370. execute command denied to user 'yb'#'%' for routine 'company.JSON_LENGTH'
Hope the question is clear enough. let me know if i need to clarify anything.
If I followed you correctly, you could simply extend the logic of your existing query (which, by the way, seems to be missing a GROUP BY clause). Instead of querying the aggregated data, it would be simpler to start from the original data, like:
SELECT
email_entry_id,
GROUP_CONCAT(attribution_string ORDER BY visit_date SEPARATOR ',' ) as channels,
COUNT(*) as `count`,
1/COUNT(*) as weight
FROM database
GROUP BY email_entry_id
There is a very common trick to achieve such outcome, demonstrated by following query
SELECT ID, PATH,
(LENGTH(PATH) - LENGTH(REPLACE(PATH, ',', ''))) + 1 COUNT
FROM DATABASE /* OR WHATEVER IS THE TABLE NAME */
The result

How to properly format overlapping mySQL IN and NOT IN conditions

I have the following mySQL table:
data
1
2
3
4
5
6
7
8
9
I would like to supply my select statement with two seperate lists
Exculde List:
1,4,5,7
Include List:
1,2,3,4,5,6,7
I tried the following statement:
Select * FROM table WHERE data NOT IN ('1,4,5,7') AND data IN ('1,2,3,4,5,6,7)
Expecting the following output:
data
2
3
6
But I received no results. I realize I passed an impossible condition but I don't know how to format my query to return the expected results.
Can anyone tell me what I'm doing wrong here?
IN takes a list of values, not a string that holds a delimited list of values.
Examples:
x IN (1, 2, 3)
x IN ('a', 'b', 'c')
Use IN (1,2,3) and not IN ('1,2,3') as the former compares to individual values 1, 2 and 3 while the latter is against the literal string 1,2,3.
Select * FROM ( (Select * FROM table WHERE data NOT IN ('1,4,5,7') ) AS table WHERE data IN ('1,2,3,4,5,6,7)
you try againt

MYSQL - Find rows, where part of search string matches part of value in column

I wasn't able to find this anywhere, here's my problem:
I have a string like '1 2 3 4 5' and then I have a mysql table that has a column, let's call it numbers, that look like this:
numbers
1 2 6 8 9 14
3
1 5 3 6 9
7 8 9 23 44
10
I am trying to find the easiest way (hopefully in a single query) to find the rows, where any of the numbers in my search string (1 or 2 or 3 or 4 or 5) is contained in the numbers column. In the give example I am looking for rows with 1,2 and 3 (since they share numbers with my search string).
I am trying to do this with a single query and no loops.
Thanks!
The best solution would be to get rid of the column containing a list of values, and use a schema where each value is in its own row. Then you can use WHERE number IN (1, 2, 3, 4, 5) and join this with the table containing the rest of the data.
But if you can't change the schema, you can use a regular expression.
SELECT *
FROM yourTable
WHERE numbers REGEXP '[[:<:]](1|2|3|4|5)[[:<:]]'
[[:<:]] and [[:<:]] match the beginning and end of words.
Note that this type of search will be very slow if the table is large, because it's not feasible to index it.
Here is a start point (split string function) : http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/ := SplitString(string,delimiter,position)
Create a function so it converts a string to an array := stringSplitted(string,delimiter)
Create a function so it compares two arrays :=arrayIntersect(array1, array2)
SELECT numbers
FROM table
WHERE arrayIntersect(#argument, numbers)
Two function definitions with loops and one single query without any loop
SELECT * FROM MyTable WHERE (numbers LIKE '%1%' OR numbers LIKE '%2%')
or you can also use REGEX something like this
SELECT * FROM events WHERE id REGEXP '5587$'

SQL ORDER BY dilemma with numbers

I have a table which holds a varchar datatype. It holds 128 characters max.
I'm trying to order it alphabetically, and it works out fine, except for one little thing.
When I try to save a mixture of numbers and letters, it returns the 'literal' alphabetical order, which means 11 comes first before 2.
I have read almost all of the answers in the internet, but they are all workarounds that cannot work specifically for my problem.
Examples of values I want to put in order
Apartment
House
Dog
Cat
18 years old
2 years old
1 year old
But I want it to look like this.
1 year old
2 years old
18 years old
Apartment
Cat
Dog
House
It spans on a large database and I can't just split the numerical values apart from the text ones.
Also users who can use the program can modify it with Alphanumeric characters.
Any suggestions about my problem? Thanks.
Here is something I tried in SQL Server. It's neither elegant nor fit for production, but it may give you an idea.
SELECT StringValue,
CAST(SUBSTRING(StringValue, StartPos, EndPos - StartPos) AS INT) AsNumber,
SUBSTRING(StringValue, StartPos, EndPos - StartPos) NumberToken,
SUBSTRING(StringValue, EndPos, 1000) Rest,
StartPos,
EndPos
FROM
(SELECT
StringValue,
PATINDEX('[0-9]%', StringValue) StartPos,
PATINDEX('%[^0-9]%', StringValue) EndPos
FROM
(SELECT 'abc123xyz' StringValue
UNION SELECT '1abc'
UNION SELECT '11abc'
UNION SELECT '2abc'
UNION SELECT '100 zasdfasd') Sub1
) Sub2
ORDER BY AsNumber, Rest
Result:
StringValue AsNumber NumberToken Rest StartPos EndPos
abc123xyz 0 abc123xyz 0 1
1abc 1 1 abc 1 2
2abc 2 2 abc 1 2
11abc 11 11 abc 1 3
100 zasdfasd 100 100 zasdfasd 1 4
I would approach this as follows...
First, write an expression to convert the numeric stuff to integers, something like
select CAST(SUBSTRING(<field>',1,instr(<field>',' ') as INT),<field>
I would then use a UNION ALL statement, something like this
SELECT CAST(SUBSTRING(<field>',1,instr(<field>',' ') as INT),<field>,A.*
FROM <table> A
WHERE <field> LIKE <regular expression to get fields beginning with numbers>
UNION ALL
SELECT 999999,<field>,A.*
FROM <table> A
WHERE <field> NOT LIKE <regular expression to get fields beginning with numbers>
ORDER BY 1,2,3
The numbers will appear first, in numeric order. Sine all of the alpha data has the same numeric key, it will appear sorted alphabetically after the numbers... Just be sure to make the alpha dummy key (999999) is large enough to be after all the numeric ones...
I don't have mySQL on this machine, but hopefully this gives you enough of a start to solve it
you should probably get away by doing something like this:
order by right(replicate(' ',30)+Column_name,30)
Try this order by:
ORDER BY RIGHT(REPLICATE('0',128)+value,128)
My test:
DECLARE #T TABLE
(
value VARCHAR(128)
)
INSERT INTO #T VALUES('Apartment'),
('House'),
('Dog'),
('Cat'),
('18 years old'),
('2 years old'),
('1 year old'),
('12 horses'),
('1 horse')
SELECT * FROM #T
ORDER BY RIGHT(REPLICATE('0',128)+value,128)
RESULTS:
Cat
Dog
House
1 horse
12 horses
Apartment
1 year old
2 years old
18 years old
If you find a case that this doesn't work please post it along with the sort order you would like and I can see if there's a fix.