SQL Specific LIKE ANY String Search - sql

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.

Related

Rebuild query which looking for specific string

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%'

Is there away in SQL Server to sort by the number of matched words in a contains function on a full text index

I have a table in a database that has a description of an item. I want to be able to have the user type a search term and return the rows that had at least one match, sorted by the number of matches they had, descending.
I don't know if this is possible, I haven't been able to find an answer googling so I'm coming here.
Basically if the user enters "truck blue with gold two tone", this will be generated:
SELECT * FROM MyItemsTable
WHERE contains(Description, 'truck or blue or with or gold or two or tone')
and have that return sorted by the number of words that matched.
Any advice would be greatly appreciated. This table will become very large in time so efficiency is also in the back of my mind as well.
This seems to have worked very well, thanks very much to Gordon Linoff.
SELECT * FROM MyItemsTable m
INNER JOIN
CONTAINSTABLE(MyItemsTable, Description, 'truck or blue or with or gold or two or tone') AS l ON m.MyItemsTable=l.[KEY]
Reference
In case you have a record like "truck blue with gold two tone". You can use below query.
SELECT * FROM
MyItemsTable as t
JOIN CONTAINSTABLE(MyItemsTable , Description,'"truck"') fulltextSearch
ON
t.[Id] = fulltextSearch.[KEY]
This will also bring this record.

SQL Multiple IN statements on one column

Okay, I'm using WordPress, but this pertains to the SQL side.
I have a query in which I need to filter out posts using three different categories, but they're all terms in the post.
For example:
In my three categories, I select the following: (Academia,Webdevelopment) (Fulltime,Parttime) (Earlycareer).
Now what I want to do is make sure when I query that the post has AT LEAST ONE of each of those terms.
CORRECT RESULT: A post with tags Academia, Fulltime, Earlycareer
INCORRECT RESULT: A post with tags Academia, Earlycareer (doesn't have fulltime or parttime)
Currently, my query looks something like this:
SELECT * FROM $wpdb->posts WHERE
(
$wpdb->terms.slug IN (list of selected from category 1) AND
$wpdb->terms.slug IN (list of selected from category 2) AND
$wpdb->terms.slug IN (list of selected from category 3)
)
AND $wpdb->term_taxonomy.taxonomy = 'jobtype' AND .......
When using this query, it returns no results when I select across the different categories (that is, I can choose 4 things from category 1 and it has results, but I can't choose anything from category 2 or 3. And vice versa)
I'm not sure if this is something to do with using IN more than once on the same column.
Thanks in advance for any help!
Your query seems to be correct. There is no any limitations in SQL about using IN for the same column miltimple times.
But ensure that you don't have any NULL values in your list of selected from category 1/2/3 queries. Even single NULL value in these lists will give NULL as a result of whole 'WHERE' condition and you will get nothing as a result.
If this won't help then it must be WordPress issue.

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.

Group keywords by site

I am finding a lot of useful help here today, and I really appreciate it. This should be the last one for the day:
I have a list of the top 10 keywords per site, sorted by visits, by date. The records need to be sorted as follows (excuse the formatting):
2010-05 2010-04
site1.com keyword1 apples wine
keyword1 visits 100 12
keyword2 oranges water
keyword2 visits 99 10
site2.com keyword1 blueberry cornbread
keyword1 visits 90 100
keyword2 squares biscuits
keyword2 visits 80 99
Basically what I need to accomplish involves grouping, but I can't seem to figure it out. Am I heading down the right path, or is there another way to achieve this, or is it just impossible?
Edit:
The dataset is something like this (csv):
site_name,date,keyword,visits
site1.com,2010-04,apples,100
site1.com,2010-04,oranges,99
site1.com,2010-05,wine,12
site1.com,2010-05,water,10
site2.com,2010-04,cornbread,100
site2.com,2010-04,biscuits,99
site2.com,2010-05,blueberry,90
site2.com,2010-05,squares,80
Across the X-axis, we need to have the 'date' value
Across the Y-axis, we need to have the 'site_name' as the primary value, but grouped within that we need to have the 'keyword' followed by the respective 'visits'.
Ok, I think you are going down the right track. It's a little tricky getting the groups right, but this should be able to be solved with grouping.
What it looks like you need is a matrix (the table where you can have dynamic rows and columns) and put the dates in a group across the top. Then group the rows by site name and then (I think) by keyword.
If grouping by keyword doesn't work, try grouping by the row number instead (within the scope of the site name group)? If this doesn't work, try getting your database to produce an extra column with rank in it first. Then you can definitely group by that. What I mean is:
site_name,date,keyword,visits,rank
site1.com,2010-04,apples,100,1
site1.com,2010-04,oranges,99,2
site1.com,2010-05,wine,12,1
site1.com,2010-05,water,10,2
site2.com,2010-04,cornbread,100,1
site2.com,2010-04,biscuits,99,2
site2.com,2010-05,blueberry,90,1
site2.com,2010-05,squares,80,2
You should then be able to add two rows in that group to put the keyword and visits in. If you can't, you might have to resort to fancy rectangle work - in the detail cell, put a rectangle, then two textboxes, with the keyword in the top one and the number of visits in the bottom one.
Create a row grouping on "site" then a child/sub row grouping on "keyword"
You don't need to use a Matrix as you know how many columns you will have, so you can just do it in a table
So the grouping would be something like
=Fields!site_name
with the same value appearing in the text box
then for the next grouping down
=Fields!keyword
ditto for the textbox
you can just use SUM to figure out how many vists =SUM(Fields!vists)
in the group total