MySQL SUBSTR LOCATE multi-search-strings - mysql

Tricky one, and my brain is mush after staring at my screen for about an hour.
I'm trying to query my database to return the first part of a string (domain name eg. http://www.example.com) in the column image_link.
I have managed this for all rows where the image_link contains .com as part of the string... but I need the code to be more versatile, so it searches for the likes of .net and .co.uk too.
Had thought some sort of nested REPLACE might work, but it doesn't make sense when I try to apply it - and I'm stuck.
Query Builder code:
$builder->select("SUBSTRING(image_link, 1, LOCATE('.com', image_link) + 3) AS domain");
Example strings, with desired results:
http://www.example.com/brands/567.jpg // http://www.example.com
https://www.example.org/photo.png // https://www.example.org
http://example.net/789 // http://example.net
Any help/advice warmly welcomed!

SELECT ... ,
SUBSTRING_INDEX(image_link, '/', 3) domain
FROM test;
Or, if protocol may be absent, then
SELECT ... ,
SUBSTRING_INDEX(image_link, '/', CASE WHEN LOCATE('//', image_link) THEN 3 ELSE 1 END) domain
FROM test;
fiddle

Related

MySQL Stored Procedure with Parameters for Recursive CTE

I'm working on a MySQL Way of printing an "affiliate tree" and got the thing working with Common Table Expression. I'm using the following code right now:
WITH RECURSIVE recUsers AS
(
SELECT ID, username, sponsorID, 1 AS depth, username AS path
FROM users
WHERE id = 1
UNION ALL
SELECT c.ID, c.username, c.sponsorID, sc.depth + 1, CONCAT(sc.path, ' > ', c.username)
FROM recUsers AS sc
JOIN users AS c ON sc.ID = c.sponsorID
)
SELECT * FROM recUsers;
This selects the tree underneath the user with the id 1.
Now what I'd need to get is a way to pass that id as a parameter, so I don't need to define everything from the beginning every time I want to get the result.. So my idea is to put everything in a stored prodecure and pass the id in as a parameter.. However, so far I didn't get it working and always getting various errors that are very self speaking...
Basically what I've tried was
DELIMITER //
CREATE PROCEDURE getAffiliateTree(IN userid INT())
BEGIN
---my code here, the userid 1 replaced with userid
END//
DELIMITER;
However, this doesn't seem to work.. How can I get this done?
Two things I would suggest:
Use INT, not INT(). The optional length argument to integer types is deprecated in MySQL 8.0 (which I know you're using, because you're using CTE syntax). Even if you did use the length argument, using an empty argument is not legal syntax.
Make sure that the userid input parameter name is distinct from all of the columns in the tables you reference. That is, if the table has a column named userid (any capitalization), then change the name of your input parameter. Otherwise you may make ambiguous expressions like:
... WHERE userid = userid
Even though you intend one of these to be the column and the other to be the parameter, the SQL parser has no way of knowing that. It ends up treating both as the column name, so it's trivially true on all rows of the table.
Actually, a third thing I would suggest: when you ask questions, "it doesn't seem to work" isn't clear enough. Did it produce an error? If so, what was the full error message? Did it produce no error, but didn't give you the result you wanted? If so, show a mocked-up example of what you expected, and what the query produced that didn't match. It helps to be as clear as you can when you post questions, so readers don't have to guess what trouble you need help with.

looking for REGEXP_REPLACE() alternative on MySQL 5.7.27

I made a query on one of the projects i m working on (On MariaDB 10.1.37):
SELECT * FROM table WHERE REGEXP_REPLACE(substring_index(product,' ',1), '[^a-zA-Z ]', '')='VALUE'
Where goal was:
1) from value select part till first space: example VALUE1 SOME OTHER to get VALUE1
2) to remove numbers and any other symbol: example VALUE1 to get VALUE
And query above does the trick as needed!
Issue is that on client side there is MySQL 5.7.27 and as we know REGEXP_REPLACE() came in MySQL on 8+ version
For now there are no options to upgrade client side to MySQL 8+ or migrate to MariaBD so the question is how and can i achieve the same result in MySQL 5.7.27?
I tried to search and tried WHERE substring_index(product,' ',1) REGEXP '^a-zA-Z' = 'VALUE' but REGEXP returns 1 or 0 and it is not what works for me as i need value. …
Any help?
Thanks in advance!
'Been searching for a solution as well since my mates are on MYSQL 5.5 and therefore they don't have REGEXP_REPLACE() either.
It's easy to find the solution on stackOverFlow for replacing just one char, but couldn't find for a string, therefore I've created that piece of code, it could help someone :
SET #string = 'I love shop it is a terrific shop, I love eveything about it';
SET #shop_code = 'shop';
SET #shop_date = CONCAT(#shop_code, '__', DATE_FORMAT(NOW(), '%Y_%m_%d__%Hh%im%ss'));
SET #part1 = SUBSTRING_INDEX(#string, #shop_code, 1);
SET #shop_nb = ROUND( (LENGTH(#string) - LENGTH(REPLACE(#string, #shop_code,''))) / LENGTH(#shop_code) );
SET #part2 = SUBSTRING_INDEX(#string, #shop_code, -#shop_nb);
SET #string = CONCAT(#part1, #shop_date, #part2);
SELECT #string;
This is not a final answer and if someone have a good or closer example to what i have asked then go ahead and post an answer. I would like to see it!
What i did is i just used LIKE
SELECT * FROM table WHERE substring_index(product,' ',1) LIKE 'VALUE%'
I know that this can show wrong data for some case but for my needs this way is acceptable.
This works in MySQL 5.7... This example would be extracting a UTM_Source parameter value from a URL's query string:
case when url like '%utm_source%' then
substring(
url,
locate('utm_source=',url)+char_length('utm_source='),
case when locate('&',url,locate('utm_source=',url)) = 0 then char_length(url)+1 else locate('&',url,locate('utm_source=',url)) end - (locate('utm_source=',url)+char_length('utm_source='))
) else NULL end utm_source;

SQL Querying inside XML column

Am trying to Query inside an SQL table which has XML Column .
Table name: 'Purchase'
Column name: 'XML_COL'
Please find below xml data for column name 'XML_COL' under purchase table:
<ns1:Request xmlns:ns1="http://www.sample.com/hic/event/request"
xmlns:ns2="http://www.sample.com/hic/eventpayload/request">
<ns1:createeventRequest>
<ns1:eventPayLoad>
<ns2:eventPayLoad>
<Id>123456</Id>
</ns2:eventPayLoad>
</ns1:eventPayLoad>
</ns1:createeventRequest>
</ns1:Request>
I have written below query :
`select * from purchase,
XMLTABLE ('$d/Request/createeventRequest/eventPayLoad/eventPayLoad' PASSING XML_COL as "d"
COLUMNS
Id varchar(20) PATH 'Id') as a where(a.Id like '1234%');`
But this is returning me an empty column with no data.
But my requirement is it should fetch all the data for this particular Id.
Please help if any one faced this kind of issue.
Do we need to include namespaces as well while querying?? or am I missing any thing?
I think the expression PATH 'Id' is bit to simple...
I'm not familiar with MySQL's abilities to query XML... The Path Id would try to find an element "Id" from the current node (which is the root node in the first action). But there is no "Id"... You must either specify the full path, starting with a single / to start at the root node, or let the engine try a deep search, starting with two //
These paths should work:
SELECT ExtractValue(
'<ns1:Request xmlns:ns1="http://www.sample.com/hic/event/request" xmlns:ns2="http://www.sample.com/hic/eventpayload/request">
<ns1:createeventRequest>
<ns1:eventPayLoad>
<ns2:eventPayLoad>
<Id>123456</Id>
</ns2:eventPayLoad>
</ns1:eventPayLoad>
</ns1:createeventRequest>
</ns1:Request>',
'/ns1:Request[1]/ns1:createeventRequest[1]/ns1:eventPayLoad[1]/ns2:eventPayLoad[1]/Id[1]' ) AS result;
If there is only one element with a value (in your case "Id") you might use the simple deep search like this:
SELECT ExtractValue(
'<ns1:Request xmlns:ns1="http://www.sample.com/hic/event/request" xmlns:ns2="http://www.sample.com/hic/eventpayload/request">
<ns1:createeventRequest>
<ns1:eventPayLoad>
<ns2:eventPayLoad>
<Id>123456</Id>
</ns2:eventPayLoad>
</ns1:eventPayLoad>
</ns1:createeventRequest>
</ns1:Request>',
'//Id[1]' ) AS result;
But - in general - it is good advise to be as specific as possible...
Just cracked the query...When name spaces are being used in an XML, instead of the entire path, I found it's better to use '/*//' which traverses through the required element tag through XML.
Final Query:
select * from purchase,
XMLTABLE('$d' PASSING XML_COL as "d"
COLUMNS
Id varchar(20) PATH '/*//Id') as a where(a.Id like '1234%') with ur
Using 'with ur' helps to read the data that has not been committed in the database.
Please post comments if it is helpful.

Mysql Query Request

Straight to the point and this might be very simple for some of you.
I have a simple SELECT query (select description from table) which produces all i want like below :
- testword123
- testword875
- myjob1 45
- myjob is 544
What i need is to have as a result :
- testword
- myjob
I can use a SELECT distinct LEFT(description,8) which works fine, but the problem is not ALL 'description' have the same number of words :-(
So basically, what i want is retrieve ONLY the letters from the 'description' result set.
Thanks!!
R
SELECT distinct LEFT(description, charindex(' ', description) - 1)
Depending on your implementation, it might be possible to declare 'description' as a variable beforehand so you don't have to type it twice in the same query.
There are two decisions:
1) Handle each decription in PHP
or
2) Handle user input before writing it to DB. Add field to table as index of first not letter symbol and then use it in LEFT mysql function
Thanks "undefined_variable" - Your solution "stackoverflow.com/questions/11134452/…; was the correct one!! (y) (with a little bit of tweaking, this helped A LOT) A+++

Combine 'like' and 'in' in a SqlServer Reporting Services query?

The following doesn't work, but something like this is what I'm looking for.
select *
from Products
where Description like (#SearchedDescription + %)
SSRS uses the # operator in-front of a parameter to simulate an 'in', and I'm not finding a way to match up a string to a list of strings.
There are a few options on how to use a LIKE operator with a parameter.
OPTION 1
If you add the % to the parameter value, then you can customize how the LIKE filter will be processed. For instance, your query could be:
SELECT name
FROM master.dbo.sysobjects
WHERE name LIKE #ReportParameter1
For the data set to use the LIKE statement properly, then you could use a parameter value like sysa%. When I tested a sample report in SSRS 2008 using this code, I returned the following four tables:
sysallocunits
sysaudacts
sysasymkeys
sysaltfiles
OPTION 2
Another way to do this that doesn't require the user to add any '%' symbol is to generate a variable that has the code and exceute the variable.
DECLARE #DynamicSQL NVARCHAR(MAX)
SET #DynamicSQL =
'SELECT name, id, xtype
FROM dbo.sysobjects
WHERE name LIKE ''' + #ReportParameter1 + '%''
'
EXEC (#DynamicSQL)
This will give you finer controller over how the LIKE statement will be used. If you don't want users to inject any additional operators, then you can always add code to strip out non alpha-numeric characters before merging it into the final query.
OPTION 3
You can create a stored procedure that controls this functionality. I generally prefer to use stored procedures as data sources for SSRS and never allow dynamically generated SQL, but that's just a preference of mine. This helps with discoverability when performing dependency analysis checks and also allows you to ensure optimal query performance.
OPTION 4
Create a .NET code assembly that helps dynamically generate the SQL code. I think this is overkill and a poor choice at best, but it could work conceivably.
Have you tried to do:
select * from Products where Description like (#SearchedDescription + '%')
(Putting single quotes around the % sign?)
Dano, which version of SSRS are you using? If it's RS2000, the multi-parameter list is
not officially supported, but there is a workaround....
put like this:
select *
from tsStudent
where studentName like #SName+'%'
I know this is super old, but this came up in my search to solve the same problem, and I wound up using a solution not described here. I'm adding a new potential solution to help whomever else might follow.
As written, this solution only works in SQL Server 2016 and later, but can be adapted for older versions by writing a custom string_split UDF, and by using a subquery instead of a CTE.
First, map your #SearchedDescription into your Dataset as a single string using JOIN:
=JOIN(#SearchedDedscription, ",")
Then use STRING_SPLIT to map your "A,B,C,D" kind of string into a tabular structure.
;with
SearchTerms as (
select distinct
Value
from
string_split(#SearchedDescription, ',')
)
select distinct
*
from
Products
inner join SearchTerms on
Products.Description like SearchTerms.Value + '%'
If someone adds the same search term multiple times, this would duplicate rows in the result set. Similarly, a single product could match multiple search terms. I've added distinct to both the SearchTerms CTE and the main query to try to suppress this inappropriate row duplication.
If your query is more complex (including results from other joins) then this could become an increasingly big problem. Just be aware of it, it's the main drawback of this method.