A cleaner implementation rather than using LIKE - performance

I have a table which contains Email Domains separated by semi-colons.
Domain
------
gmail.com;googlemail.com
hotmail.com;hotmail.co.uk;live.co.uk
I am currently running the following SQL:
SELECT [Id]
FROM [DomainGroup]
WHERE [Domain] LIKE '%' + (SELECT RIGHT('anemail#gmail.com', CHARINDEX('#', REVERSE('anemail#gmail.com')) - 1)) + '%'
Although this is working, I was thinking that maybe using PATINDEX would be better, from both performance and readability. The email address is actually a variable, but I've put it in to show what I'm trying to achieve.

I think the performance benefit of PATINDEX vs LIKE is at best ambiguous, particularly in your case given that normalizing the delimited values to individual rows in an indexed column would give more of a performance boost than anything else.
If you can't change design & want to use PATINDEX, then I would pre-compute the pattern;
declare #emaildomain varchar(128) = 'anemail#gmail.com'
set #emaildomain = '%;' + stuff(#emaildomain, 1, charindex('#', #emaildomain), '') + ';%'
Then use that in the where clause;
where patindex(#emaildomain, ';' + [Domain] + ';') > 0
(I padded with ; delimiters so aaa#bbb.com would not match aaabbb.com;)

Have you considered using fulltext search?
After creating the index, queries would look like:
SELECT [Id] FROM [DomainGroup] WHERE CONTAINS ([Domain], 'gmail.com')

Related

ORACLE detecting duplicate data even the text is lower or uppercase

I'm using ORACLE database. How to detect duplicate data even the text is lower or uppercase.
Assuming on my table already inserted : Production
Now I want to add: production (with lower case), it should be detect duplicate. In my current case, it was not detected and inserted.
Here is the sample query:
SELECT * FROM tb_departments WHERE DEPARTMENT_NAME = '" . $getDepartmentName . "';
Anyone have an idea?
You can use the UPPER (or LOWER) function, which capitalize your string, i.e.
SELECT * FROM tb_departments WHERE UPPER(DEPARTMENT_NAME) = UPPER('" . $getDepartmentName . "');
As small variation you could capitalize your input string in the code and use
SELECT * FROM tb_departments WHERE UPPER(DEPARTMENT_NAME) = '" . $yourUpperDepartmentName . "';
Moreover I suggest you use query parameters, instead of injecting directly the parameters string ($getDepartmentName ) in your query.

Oracle query with two paterns in one expression

Input:
TABLE NAME: SEARCH_RECORD
Column A Column B Column C Column D
ID CODE WORD CODE/WORD
--------------------------------------------
123 666Ani RAT 666Ani/RAT
124 777Cae CAT 777Cae/CAT
I need a query to check as a LIKE case
if i search with column B like '%6A' or column C '%A%' it will give result
suppose i want to get the like based on the column D search
**User will search like '%6A%'/'%AT%' (always / will be given by user)**
Expected output:
666Ani/RAT
so, I need a query for the above to get the ID as output (CASE query is preferable)
Need you valuable suggestion
.
It can't be done with simple like.
It should work if the pattern look like '%6A%/%AT%'. It is a valid pattern.
So, you can write: columnD like '%6A%/%AT%' or columnD like first_pattern||'/'||second_pattern if the come from as different variables.
Another approach, if you know for sure that there is only a /(you can check how many they are), may be to use two likes using substr to get first and then second part of the search string.
where
columnB like substr(match_string, 1, instr(match_string,'/'))
and
columnC like substr(match_string, instr(match_string,'/')+1)

Oracle 9i Sub query

Hi Can any one help me out of this query forming logic
SELECT C.CPPID, c.CPP_AMT_MANUAL
FROM CPP_PRCNT CC,CPP_VIEW c
WHERE
CC.CPPYR IN (
SELECT C.YEAR FROM CPP_VIEW_VIEW C WHERE UPPER(C.CPPNO) = UPPER('123')
AND C.CPP_CODE ='CPP000000000053'
and TO_CHAR(c.CPP_DATE,'YYYY/Mon')='2012/Nov'
)
AND UPPER(C.CPPNO) = UPPER('123')
AND C.CPP_CODE ='CPP000000000053'
and TO_CHAR(c.CPP_DATE,'YYYY/Mon') = '2012/Nov';
Please Correct me if i formed wrong query structure, in terms of query Performance and Standards. Thanks in Advance
If you have some indexes or partitioned tables I would not use functions on columns but on variables, to be able to use indexes/select partitions.
Also I use ANSI 92 SQL syntax. You don't specify(or not directly) a join contition between cpp_prcnt and cpp_view so it is actually a cartesian product(cross join)
SELECT C.CPPID, c.CPP_AMT_MANUAL
FROM CPP_PRCNT CC
CROSS JOIN CPP_VIEW c
WHERE
CC.CPPYR IN (
SELECT C.YEAR
FROM CPP_VIEW_VIEW C
WHERE C.CPPNO = '123'
AND C.CPP_CODE ='CPP000000000053'
AND trunc(c.CPP_DATE,'MM')=to_date('2012/Nov','YYYY/Mon')
)
AND C.CPPNO = '123'
AND C.CPP_CODE ='CPP000000000053'
AND trunc(c.CPP_DATE,'MM')=to_date('2012/Nov','YYYY/Mon')
If you show us the definition of cpp_view_view(seems to be a view over cpp_view), the definition(if simple) of CPP_VIEW and what you're trying to achieve, I bet there are more things to be improved/fixed.
There are a couple of things you could improve:
if possible, get rid of the UPPER() in the comparison - this will render any indices useless. If that's not possible, consider a function-based index on UPPER(CPPNO)
do not convert your DATE column to a string to compare it with a string - do it the other way round (i.e. convert your string to a date => only one conversion needed instead of one per table row, use of indices possible)
play around with EXISTS instead of IN, as suggested by Dileep - might be faster

VS 2010 reporting services grouping

I want to load the list of the groups as well as data into two separate datatables (or one, but I don't see that possible). Then I want to apply the grouping like this:
Groups
A
B
Bar
C
Car
Data
Ale
Beer
Bartender
Barry
Coal
Calm
Carbon
The final result after grouping should be like this.
*A
Ale
*B
*Bar
Bartender
Barry
Beer
*C
Calm
*Car
Carbon
Coal
I only have a grouping list, not the levels or anything else. And the items falling under the certain group are the ones that do start with the same letters as a group's name. The indentation is not a must. Hopefully my example clarifies what I need, but am not able to name thus I am unable to find anything similar on google.
The key things here are:
1. Grouping by a provided list of groups
2. There can be unlimited layers of grouping
Since every record has it's children, the query should also take a father for each record. Then there is a nice trick in advanced grouping tab. Choosing a father's column yields as many higher level groups as needed recursively. I learnt about that in http://blogs.microsoft.co.il/blogs/barbaro/archive/2008/12/01/creating-sum-for-a-group-with-recursion-in-ssrs.aspx
I suggest reporting from a query like this:
select gtop.category top_category,
gsub.category sub_category,
dtab.category data_category
from groupTable gtop
join groupTable gsub on gsub.category like gtop.category + '%'
left join dataTable dtab on dtab.category like gsub.category + '%'
where len(gtop.category) = 1 and
not exists
(select null
from groupTable gchk
where gsub.category = gtop.category and
gchk.category like gsub.category + '%' and
gchk.category <> gsub.category and
dtab.category like gchk.category + '%')
- with report groups on top_category and sub_category, and headings for both groups. You will probably want to hide the sub_category heading row when sub_category = top_category.

data structure algorithms for database searching

I was used to the traditional way of doing database searching with the following
using wildcards for term searches
using where clause for specific data like addresses and names
but at other times, I found these common methods to produce code that is so bloated, especially when it comes to complex searches.
Are there algorithms out there that you use for complex database searching? I tried to look for some but had a hard time doing so. I stumbled accross the binary search but I can't find a use for it :(
EDIT: Here's a pseudocode of a search I was working on. It uses jquery range sliders for maximum and minimum searching
query = 'select * from table'
if set minprice and not set maxprice
if minprice = 'nomin'
query += ' where price < maxprice'
else
query += ' where price < maxprice and price < minprice'
if not set minprice and set maxprice
if maxprice = 'nomax'
query += ' where price > minprice'
else
query += ' where price > minprice and price < maxprice'
if set maxprice and set minprice
if maxprice = 'nomax'
query += ' where price > minprice'
else
query += ' where price > minprice and price < maxprice'
this may not be the codebase by which you base your answers. I'm looking for more elegant ways of doing database searching.
EDIT by elegant I mean ways of rewriting the code to to achieve faster queries at less lines of code
Alright, I'm still not very clear on what you want, but I'll give it a shot...
If you're trying to speed up the query, you don't need to worry about "improved algorithms". Just make sure that any columns that you're searching on (price in your example) have an index on them, and the database will take care of searching efficiently. It's very good at it, I promise.
As for reducing the amount of code, again, I can't speak for every case, but your above pseudocode is bloated because you're handling the exact same case multiple times. My code for something like that would be more like this (pseudocode, no particular language):
if (set(minprice) and minprice != 'nomin')
conditions[] = 'price > minprice'
if (set(maxprice) and maxprice != 'nomax')
conditions[] = 'price < maxprice'
query = 'select * from table'
if (notempty(conditions))
query += ' where '+conditions.join(' and ')
Remeber speed of a query is not just the query itself. Also, greatly depends on how the db is structured. Is this a std relational layout, or a star, or? Are your keys indexed, and do you have secondary indexes? Are you expecting to bring back a lot of data, or just a couple of rows? Are you searching on columns where the db has to do a text search, or on numeric values. And of course, on top of that, how is the db physically layed out? index's and heavy hit tables on seperate drives? and so forth. Like the previous people mentioned, maybe a specific example would be more helpful in trying to solve
When interfacing with a database, you're far better off with a complex and ugly query than with an 'elegant' query which has you duplicating database search functionality inside your application. Each call to the database has a cost associated with it. If you write code to search a database within your application, it's virtually guaranteed to be more expensive.
Unless you are actually writing a database (tall order), let the database do the searching.
try to focus on reorganizing your query building process.
query = select + ' where ' + filter1 + filter2
select = 'select * from table'
filter1 = '';
if set minprice
if minprice = 'nomin'
filter1 = price > minprice'
else
filter1 = 'price < minprice'
and so on ... 'til the building the full query :
query = select;
if any filter on
query += ' where '
first = true
if set filter 1
if not first
query += ' and '
query += filter1
and so on...
you can put your filters in an array. it is more 'scalable' for your code.
The major problem with your code is that it unnecessarily mulls over every possible combination of set(minprice) and set(maxprice), while they can be treated independently:
query = 'select * from table'
conditions = [] #array of strings representing conditions
if set(minprice):
conditions.append("price < minprice")
if set(maxprice):
conditions.append("price > maxprice")
if len(conditions)>0:
query += ' WHERE ' + " and ".join(conditions)
In general it is beneficial to separate generation of conditions (the if set(...) lines above) from building the actual query. This way you don't need a separate if to generate (or skip) an "AND" or "WHERE" before each generated condition but instead you can just process it in one place (the last two lines above) adding the infixes as necessary.

Resources