Rebuild query which looking for specific string - sql

I have products numbers which looks like below:
One example product (contain couple articles)
14.12312.1
14.12312.2
14.12312.3
14.12312.4
14.12312.5
Other example product (contain couple articles)
003.23.1
003.23.66
003.23.44
003.23.77
003.23.5
Important thing here is dots are separators:
<producentNumber>.<specialnumber>.<articlevariation>
Now i got query which could take first part of specific product for instance i can pass: 003.23. (with last dot) and then it gives me all starts with it so:
003.23.1
003.23.66
003.23.44
003.23.77
003.23.5
This is the query which is doing that:
SELECT ID, Nummer FROM [Cenea].[dbo].[T_Artikel]
WHERE
SUBSTRING(Nummer, 0, LEN(Nummer) + 2 - CHARINDEX('.', REVERSE(Nummer))) IN
(
'003.23.'
)
However now is the change that within last part of the articles number could appears dots and not only the numbers so it means i can have like this:
003.23.1
003.23.66..dwqd
003.23.4422.323.3
003.23.77....f
003.23.5
So when i pass 003.23. i will get not all but just 003.23.1 in this case. The logic stays as it was first two dots are holding the base but after the second there could be anything. Question is how to rebuild my sql query to adapt the change to get alkl articles?
Hope everything is clear and please provide working code as i have to make change on production today.

You can use LIKE to get all rows where Number starts with <some value>:
SELECT ID, Nummer FROM [Cenea].[dbo].[T_Artikel]
WHERE Number LIKE '003.23%'

Related

SQL Specific LIKE ANY String Search

So I'm in Teradata trying to pull any products that have more than 1 color-related name, as seen in the code snippet here:
SELECT
pt.product_number,
COUNT (CASE WHEN ot.option_name like any ('%green%', '%red%', '%blue%') THEN 1 ELSE NULL END) as differentColorCount
FROM product_table pt
JOIN option_table ot on ot.product_num = pt.product_num
HAVING differentColorCount > 1
GROUP BY 1
This is running fine, but the problem that I'm realizing is that a product might have a hundred different "Red" options for instance. (Red-1, Red-2, Red-3, etc). But I only want a count of when two of the different color strings are present for a single product.
So instead of LIKE ANY what I really need is LIKE ANY TWO. If both Red AND Green are present, count 1. If both Blue AND Purple are present, count 1.
I realize I could do a really long list where I do dozens of LIKE ALLs in every possible combination, but that doesn't seem like it will scale well if I need to check for, say 100 different colors instead of 6?
If anyone has any insight on this I would be incredibly grateful. Thanks in advance for any help you can offer! :)
You can utilize a regular expression to extract the color and then apply a distinct count:
Count (DISTINCT RegExp_Substr(option_name, '(green|red|blue)')) AS differentColorCount
This is similar to your like any ('%green%', '%red%', '%blue%'), but returns the actual matching color instead of TRUE/FALSE.
The'(green|red|blue)' search pattern seperates defines three alternative search strings and returns the first match.

How to retrieve a part of a value in a column

Correction - I only need to Pick the WORK value every result set in the column will contain comma seperated values like below..
"SICK 0.08, WORK 0.08" or "SICK 0.08,WORK 0.08"
I only need to pick WORK 0.08 from this.
I am quite new to SQL
I am using the following script to get some results;
select Work.Work_summary, Work.emp_id
from Work
all work fine. but the first column has values like the following :
WORK 08.57, SICK 08.56 (Some columns)
SICK 07.80, WORK 06.80 , OT 02.00 (Some columns)
How can i only retrieve the column with only the WORK% value, if there is no WORK value the results shall be empty.
select Work_summary, emp_id
from Work
where Work_summary like '%WORK%'
This will return the rows in the Work table where Work_summary column contains the word WORK. See the documentation for more details.
Contains is faster than like.
SELECT Work_summary, emp_id FROM Work WHERE CONTAINS(Work_summary, 'WORK');
then use: this will give only the result where work summary contains work content.
select Work.Work_summary, Work.emp_id
from Work where contains(work.Work_summary ,'work');
select replace(Work_summary,",","") as work_summary
from Work
where upper(Work_summary) like '%WORK%'

Create a select statement that turn one column into Mutliple columns using Char Index or something similar

1) Question 1 : Splitting after every 6th digit, basically I need to split my columns after every 5th digit so that 123456 creates to columns , ones with 12345 and a second with 6, I have tried using the code below with no result. there are no spaces or symbols , just digits.
substring(COA.UserCode2,5,charindex('',COA.UserCode2)) as Account,
substring(COA.UserCode2,6,charindex('',COA.UserCode2)) as Project
2) Question 2: Splitting after every * , I can get the first one below to work (Fund) but my cost center and Source don't work basically if I have a string like 1234*34*500, I need the column for fund to have 1234 ( This I got already) , my Cost center to say 34 and my source to say 500
substring(COA.UserCode3, 1,charindex('*',COA.UserCode3)) as Fund,
substring(COA.UserCode3, 3,charindex('*',COA.UserCode3)+1) as CostCenter,
substring(COA.UserCode3, 1,charindex('*',COA.UserCode3)) as Source
Not knowing what DBMS you use (if it has specific SQL extensions etcetera) or how the data looks here is at least some suggestions:
1) If the data is fixed in size (always 6 chars long) you could do this:
SUBSTRING(UserCode2,1,5) as Account, SUBSTRING(UserCode2,6,1) as Project
2) For the second question you could do any of these:
If the data is fixed:
SUBSTRING(UserCode3,1,4) as Fund,
SUBSTRING(UserCode3,6,2) as CostCenter,
SUBSTRING(UserCode3,9,2) as Source
Or if the data is variable and you have to split on the * chars:
SUBSTRING(UserCode3,1,CHARINDEX('*',UserCode3,1)-1) as Fund,
SUBSTRING(UserCode3,CHARINDEX('*',UserCode3,1)+1,CHARINDEX('*',UserCode3,CHARINDEX('*',UserCode3,1)+1) - CHARINDEX('*',UserCode3,1)-1) as CostCenter,
RIGHT(UserCode3,3) as Source
Doing this many CHARINDEX and SUBSTRING functions would probably be bad for performance, but without knowing more about the data it's a bit difficult making informed suggestions.

Custom SQL sort by

Use:
The user searches for a partial postcode such as 'RG20' which should then be displayed in a specific order. The query uses the MATCH AGAINST method in boolean mode where an example of the postcode in the database would be 'RG20 7TT' so it is able to find it.
At the same time it also matches against a list of other postcodes which are in it's radius (which is a separate query).
I can't seem to find a way to order by a partial match, e.g.:
ORDER BY FIELD(postcode, 'RG20', 'RG14', 'RG18','RG17','RG28','OX12','OX11')
DESC, city DESC
Because it's not specifically looking for RG20 7TT, I don't think it can make a partial match.
I have tried SUBSTR (postcode, -4) and looked into left and right, but I haven't had any success using 'by field' and could not find another route...
Sorry this is a bit long winded, but I'm in a bit of a bind.
A UK postcode splits into 2 parts, the last section always being 3 characters and within my database there is a space between the two if that helps at all.
Although there is a DESC after the postcodes, I do need them to display in THAT particular order (RG20, RG14 then RG18 etc..) I'm unsure if specifying descending will remove the ordering or not
Order By Case
When postcode Like 'RG20%' Then 1
When postcode Like 'RG14%' Then 2
When postcode Like 'RG18%' Then 3
When postcode Like 'RG17%' Then 4
When postcode Like 'RG28%' Then 5
When postcode Like 'OX12%' Then 6
When postcode Like 'OX11%' Then 7
Else 99
End Asc
, City Desc
You're on the right track, trimming the field down to its first four characters:
ORDER BY FIELD(LEFT(postcode, 4), 'RG20', 'RG14', ...),
-- or SUBSTRING(postcode FROM 1 FOR 4)
-- or SUBSTR(postcode, 1, 4)
Here you don't want DESC.
(If your result set contains postcodes whose prefixes do not appear in your FIELD() ordering list, you'll have a bit more work to do, since those records will otherwise appear before any explicitly ordered records you specify. Before 'RG20' in the example above.)
If you want a completely custom sorting scheme, then I only see one way to do it...
Create a table to hold the values upon which to sort, and include a "sequence" or "sort_order" field. You can then join to this table and sort by the sequence field.
One note on the sequence field. It makes sense to create it as an int as... well, sequences are often ints :)
If there is any possibility of changing the sort order, you may want to consider making it alpha numeric... It is a lot easier to insert "5A" between "5 and "6" than it is to insert a number into a sequence of integers.
Another method I use is utilising the charindex function:
order by charindex(substr(postcode,4,1),"RG20RG14RG18...",1)
I think that's the syntax anyway, I'm just doing this in SAS at the moment so I've had to adapt from memory!
But essentially the sooner you hit your desired part of the string, the higher the rank.
If you're trying to rank on a large variety of postcodes then a case statement gets pretty hefty.

No Exact match when using LIKE in SQL statement

SELECT bp.*,r.rating,COUNT(r.review_for),bp.business_name,bp.profile_member
FROM ibf_business_reviews r
LEFT JOIN ibf_business_profiles bp ON ( r.review_for=bp.profile_member )
WHERE bp.sub_category LIKE '%{$id},%'{$location_sql}
GROUP BY r.review_for HAVING COUNT(r.review_for) >=1
ORDER BY r.date_posted DESC LIMIT 0,2");
This query is used to show results for business_name in a certain sub_category id '%{$id} in a certain location. My problem is that extra results are showing in categories that share a second or third digit aka ...viewcat&id=54 will show in ..viewcat&id=154 etc
I using the LIKE may be my issue? WHERE bp.sub_category LIKE '%{$id},%'
You are storing a comma-separated list in a varchar, when you should store one number per row in a child table. Then you wouldn't have to use LIKE at all.
Read up on First Normal Form.
Here was my comment
+! for the need to reformat the SQL. You do realize that the "percent"
signs (%) are the wildcards. So you're
essentially telling it that you can
return ANYTHING that includes id... so
if you search "23" you could get
"123", you could get "234" or
"1234"... etc.
and you replied
Thanks #Rock removing the wildcards worked!
Now my answer to this is... If you removed BOTH wildcards from your string, then you're essentially doing an "equals".
IE:
WHERE bp.sub_category LIKE '{$id},'
should be the same as
WHERE bp.sub_category = '{$id},'
Because you don't have any wildcards to "match" in the "LIKE" statement.
Please forgive me if I screwed up the "$" or the ","... I'm not a MySQL guy