SQL LIKE using the same row value - sql

I'm wondering how can I use a row value as a variable for my like statement? For example
ID | PID | DESCRIPTION
1 | 4124 | Hi4124
2 | 2451 | Test
3 | 1467 | Hello
4 | 9642 | Me9642
I have a table above, I want to return IDs 1 and 4 since DESCRIPTION contains PID.
I'm thinking it would be SELECT * from TABLE WHERE DESCRIPTION LIKE '%PID%' but I can't get it.

You can use CONCAT() to assemble the matching pattern, as in:
select *
from t
where description like concat('%', PID, '%')

We could also try using CHARINDEX here:
SELECT ID, PID, DESCRIPTION
FROM yourTable
WHERE CHARINDEX(PID, DESCRIPTION) > 0;
Demo
Note that I assume in the demo that the PID column is actually text, and not a numeric column. If PID be numeric, we might have to first use a cast in order to use CHARINDEX (or any of the methods given in the other answers).

Use the CONCAT SQL function
SELECT *
FROM TABLE
WHERE DESCRIPTION LIKE CONCAT('%', PID, '%')

Related

Data field - search and write value in new data field (Oracle)

Sorry, I don't know how to describe that as a title.
With a query (example: Select SELECT PKEY, TRUNC (CREATEDFORMAT), STATISTICS FROM BUSINESS_DATA WHERE STATISTICS LIKE '% business_%'), I can display all data that contains the value "business_xxxxxx".
For example, the data field can have the following content: c01_ad; concierge_beendet; business_start; or also skill_my; pre_initial_markt; business_request; topIntMaster; concierge_start; c01_start;
Is it now possible in a temp-only output the corresponding value in another column?
So the output looks like this, for example?
PKEY | TRUNC(CREATEDFORMAT) | NEW_STATISTICS
1 | 13.06.2020 | business_start
2 | 14.06.2020 | business_request
That means removing everything that does not start with business_xxx? Is this possible in an SQL query? RegEx would not be the right one, I think.
I think you want:
select
pkey,
trunc(createdformat) createddate,
regexp_substr(statistics, 'business_\S*') new_statistics
from business_data
where statistics like '% business_%'
You can also use the following regexp_substr:
SQL> select regexp_substr(str,'business_[^;]+') as result
2 from
3 --sample data
4 (select 'skill_my; pre_initial_markt; business_request; topIntMaster; concierge_start; c01_start;' as str from dual
5 union all
6 select 'c01_ad; concierge_beendet; business_start;' from dual);
RESULT
--------------------------------------------------------------------------------
business_request
business_start
SQL>

How to write SQL queries with respect to the following conditions?

I have a database table in which a column tags contain values such as:
"AutoMNRP, MNRP"
"Macro, MNRP"
"AutoMNRP, Micro"
"Macro, Micro"
where "...." represents a string.
I want to write a SQL query such that it filters out all results having MNRP tag in it. How can I do this?
I tried a not like operator of SQL on it, but if I want to remove MNRP tag, it also filters out AutoMNRP tag.
At the last of query I need results featuring -
"AutoMNRP, Micro"
"Macro, Micro".
(Results when MNRP is filtered out.)
The right answer to this is to fix your design, you shouldn't store the data like this (comma separated), because your table should be like (and the duplicates should be removed and handled too)
+----------+
| Data |
+----------+
| AutoMNRP |
| MNRP |
| Macro |
| MNRP |
| AutoMNRP |
| Micro |
| Macro |
| Micro |
+----------+
But... here is a way it may fit you requirements
;WITH T(Str) AS
(
SELECT 'AutoMNRP, MNRP' UNION ALL
SELECT 'Macro, MNRP' UNION ALL
SELECT 'AutoMNRP, Micro' UNION ALL
SELECT 'Macro, Micro'
)
SELECT Str
FROM T
WHERE Str NOT LIKE '% MNRP,%'
AND
Str NOT LIKE '%, MNRP';
Returns:
+-----------------+
| Str |
+-----------------+
| AutoMNRP, Micro |
| Macro, Micro |
+-----------------+
Live Demo
You also (as Larnu point to) do as
;WITH T(Str) AS
(
SELECT 'AutoMNRP, MNRP' UNION ALL
SELECT 'Macro, MNRP' UNION ALL
SELECT 'AutoMNRP, Micro' UNION ALL
SELECT 'Macro, Micro'
)
SELECT Str
FROM T
WHERE CONCAT(', ', Str, ',') NOT LIKE '%, MNRP,';
In SQL Server 2016+ you can use the STRING_SPLIT function. So you can multiply a record by the number of separated values in the tags column so you can then apply a simple WHERE clause. Something like this:
WITH cte AS
(
SELECT Id, SingleTag
FROM table_name CROSS APPLY STRING_SPLIT(tags, ',')
)
SELECT * FROM cte WHERE SingleTag = 'MNRP'

select query for sql

Table description
Table Name:- Name condition
Name | Pattern
A | %A% or Name like %a%
B | %B% or Name like %b%
C | %C% or Name like %c%
D | %D% or Name like %d%
E | %E% or Name like %e%
F | %F% or Name like %f%
G | %G% or Name like %g%
Table name:- Employees
Emp_ID | EMP_NAME
1 | Akshay
2 | Akhil
3 | Gautam
4 | Esha
5 | bhavish
6 | Chetan
7 | Arun
[Table description] [1]: https://i.stack.imgur.com/wvOgr.png
Above are my two tables now my query is (in the image)
Select * from Employees,Name_condition where EMP_NAME like Pattern
Here the query is correct syntactically but produces wrong output.
It takes the column Pattern as a string and searches for it in EMP_NAME and it will find nothing.
So my question is how we can take the values present in the Pattern column as a condition and not as a string so that the query will become like this
Select * from Employees,Name_condition where EMP_NAME like ‘%A%’ or Name like ‘%a%’
what i need is when i pass colunm name(Pattern) in the where condition it takes %A% or Name like %a% whole as a string but i want that select * from Employees,Name_condition where EMP_NAME like Pattern Here the column name pattern internally must be replace by the value present in the column and the the query produces o/p like this
Select * from Employees,Name_condition where EMP_NAME like ‘%A%’ or Name like ‘%a%’
Desired Result:-I expect all the rows in my result which includes bhavish but as we see we have a like condition in the column itself like %B% or Name like %b%
What i want is when it matches
where EMP_NAME like Pattern
The value of pattern must internally replaced by
%B% or Name like %b%
and the it produces the output which includes bhavish which starts with b
try:
select *
from employees
where emp_name like '%oh%'
or emp_name like '%a%';
Good luck.
Try this from orafaq:
SELECT * FROM employees
WHERE emp_name LIKE '\%a\%' ESCAPE '\';
It's not that simple (and it shouldn't be). If you really have to use such tables you have to write a piece of PL/SQL to handle your conditions.
Two things you have to read about:
dynamic sql
sql injection (because you want to prevent it)
Try to Put && instead of 'And' in condition

Counting occurrences in a table

Lets say I want to count the total number of occurrences of a name contained within a string in a column and display that total next to all occurrences of that name in a new column beside it. For example, if I have:
Name | Home Address | Special ID
==================================
Frank | 152414 | aTRF342
Jane | 4342342 | rRFC432
Mary | 423432 | xTRF353
James | 32111111 | tLZQ399
May | 4302443 | 3TRF322
How would I count the occurrences of special tags like 'TRF', 'RFC', or 'LZQ' so the table looks like this:
Name | Home Address | Special ID | Occurrences
================================================
Frank | 152414 | aTRF342 | 3
Jane | 4342342 | rRFC432 | 1
Mary | 423432 | xTRF353 | 3
James | 32111111 | tLZQ399 | 1
May | 4302443 | 3TRF322 | 3
Currently using Access 2007. Is this even possible using a SQL query?
Using Access 2007, I stored your sample data in a table named tblUser1384831. The query below returns this result set.
Name Home Address Special ID special_tag Occurrences
---- ------------ ---------- ----------- -----------
Frank 152414 aTRF342 TRF 3
Jane 4342342 rRFC432 RFC 1
Mary 423432 xTRF353 TRF 3
James 32111111 tLZQ399 LZQ 1
May 4302443 3TRF322 TRF 3
Although your question has a vba tag, you don't need to use a VBA procedure for this. You can do it with SQL and the Mid() function.
SELECT
base.[Name],
base.[Home Address],
base.[Special ID],
base.special_tag,
tag_count.Occurrences
FROM
(
SELECT
[Name],
[Home Address],
[Special ID],
Mid([Special ID],2,3) AS special_tag
FROM tblUser1384831
) AS base
INNER JOIN
(
SELECT
Mid([Special ID],2,3) AS special_tag,
Count(*) AS Occurrences
FROM tblUser1384831
GROUP BY Mid([Special ID],2,3)
) AS tag_count
ON base.special_tag = tag_count.special_tag;
You would have to GROUP BY the substring of Special ID. In MS Access, you can read about how to compute substrings here.
The problem in your case is that your data in Special ID column does not follow a standard pattern, one which easy to extract via the substring function. You might need to use regular expressions to extract such values, and later apply the GROUP BY to them.
With MSSQL, Oracle, PostgreSQL you would be able to declare a stored procedure (example CLR function in MS SQL Server) that would do this for you. Not sure with MS Access.
you can do something like this:
select Name, [Home Address], [Special ID],
(select count(*) from [your table] where [Special ID] = RemoveNonAlphaCharacters([Special ID]) ) as Occurrences
from [your table]
auxiliar function (got from this link):
Create Function [dbo].[RemoveNonAlphaCharacters](#Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin
While PatIndex('%[^a-z]%', #Temp) > 0
Set #Temp = Stuff(#Temp, PatIndex('%[^a-z]%', #Temp), 1, '')
Return #Temp
End
lets say your first table is called 'table_with_string'
the following code will show the occurance based on the first 3 charecters of string in Special ID column. since it is not clear how exactly you are passing the string to match
select tws.Name,tws.HomeAddress,tws.SpecialID,str_count.Occurrences from
table_with_string tws
left join
(select SpecialID,count(*) from table_with_string where specialID like(substring
(specialid,0,3))
group by specialId) as str_count(id,Occurrences)
on str_count.id=tws.SpecialID
I would suggest doing this explicitly as a join, so you are clear on how it works:
select tws.Name, tws.HomeAddress, tws.SpecialID, str_count.Occurrences
from table_with_string tws
join
(
select substring(spcecialid, 2, 3) as code, count(*) as Occurrences
from table_with_string tws
group by substring(spcecialid, 2, 3)
) s
on s.code = substring(tws.spcecialid, 2, 3)

SQL Server Best match query with update (T-SQL)

I am trying to find out what's the most optimized SQL Query to achieve the following.
I have a table containing ZipCodes/PostalCodes, let's assume the following structure:
table_codes:
ID | ZipCode
---------------
1 1234
2 1235
3 456
and so on.
The users of my application fill up a profile where they are required to enter their ZipCode (PostalCode).
Assuming that sometimes, the user will enter a ZipCode not defined in my table, I am trying to suggest a Best Match based on the zip entered by the user.
I am using the following query:
Declare #entered_zipcode varchar(10)
set #entered_zipcode = '23456'
SELECT TOP 1 table_codes.ZipCode
FROM table_codes
where #entered_zipcode LIKE table_codes.ZipCode + '%'
or table_codes.ZipCode + '%' like #entered_zipcode + '%'
ORDER BY table_codes.ZipCode, LEN(table_codes.ZipCode) DESC
Basically, I am trying the following:
if the #entered_zipcode is longer than any zip code in the table, I am trying to get to get the best prefix in the zip table matching the #entered_zipcode
if the #entered_zipcode is shorter than any existing code in the table, I am trying to use it as a prefix and get the best match in the table
Moreover, I am building a temp table with the following structure:
#tmpTable
------------------------------------------------------------------------------------
ID | user1_enteredzip | user1_bestmatchzip | user2_enteredzip | user2_bestmatchzip |
------------------------------------------------------------------------------------
1 | 12 | *1234* | 4567 | **456** |
2 |
3 |
4 |
Entered zip is the one the user enters and the code between * .. * is the best matching code from my lookup table, that I am trying to get using the query below.
The query seems to take a little bit to long and this is why I am asking for help in optimizing it:
update #tmpTable
set user1_bestmatchzip = ( SELECT TOP 1
zipcode
FROM table_codes
where #tmpTable.user1_enteredzip LIKE table_codes.zipcode + '%'
or table_codes.zipcode + '%' like #tmpTable.user1_enteredzip + '%'
ORDER BY table_codes.zipcode, LEN(table_codes.zipcode) DESC
),
user2_bestmatchzip = ( SELECT TOP 1
zipcode
FROM table_codes
where #tmpTable.user2_enteredzip LIKE table_codes.zipcode + '%'
or table_codes.zipcode + '%' like #tmpTable.user2_enteredzip + '%'
ORDER BY table_codes.zipcode, LEN(table_codes.zipcode) DESC
)
from #tmpTable
What if you change your temp table to be like:
id | user | enteredzip | bestmatchzip
10 | 1 | 12345 | 12345
20 | 2 | 12 | 12345
That is: use a column to save the user number (1 or 2). This way you will update one row at a time.
Also, the ORDER BY takes time, did you set indices on the zipcode? Couldn't you create a field "length" in the zipcodes table to pre-compute the zipcodes lenghts?
EDIT:
I was thinking that ordering by LEN makes no sense, you could remove that! If the zipcodes cannot have duplicates, then ordering by the zipcode is just enought. If they can though, the LEN will always be equal!
You are comparing first characters of both strings - what if you compare substrings of minimal length?
select top 1 zipcode
from table_zipcodes
where substring(zipcode, 1, case when len(zipcode) > len (#entered_zipcode) then len(#entered_zipcode) else len (zipcode) end)
= substring (#entered_zipcode, 1, case when len(zipcode) > len (#entered_zipcode) then len(#entered_zipcode) else len (zipcode) end)
order by len (zipcode) desc
This will remove OR and allow for usage of index *in_#entered_zipcode LIKE table_codes.ZipCode + '%'*. Also, it seems to me that the ordering of results is wrong - shorter zipcodes go first.