Multiple Table Access Query - sql

I am trying to combine multiple tables in Microsoft Access to return a LIKE wildcard value. However, I want it done by a list of things, not just a specific item. I have the below table labled "SomeData"
ID Fund TextFld Type1
2 Sewer COMP - DZ Docs
3 Sewer SEW: ZO Docs
I have a second table labeled GL where in I am looking up on TextFld: For instance there might be:
COMP - ABC
COMP - DEF
SEW: GHS
SEW: XYZ
I put into SQL:
SELECT GL.Text, SomeData.Type1
FROM SomeData INNER JOIN GL ON SomeData.Fund = GL.Type
WHERE GL.Text LIKE SomeData.TextFld;
However, this is only returning exact matches. How can I do this so that any similar match will be found.
Please note that there will be many lines of these, so I cannot just use anything such as LIKE "COMP*" OR "SEW*"
Thank you very much in advance. Any help would be greatly appreciated.

You don't have the wildcard in your query. The wildcard in MS Access is the asterisk so your query should look like this:
SELECT GL.Text, SomeData.Type1
FROM SomeData INNER JOIN GL ON SomeData.Fund = GL.Type
WHERE GL.Text LIKE '*' & SomeData.TextFld & '*';
I haven't ever used a LIKE statement while using a field from another table but I'm fairly certain that syntax is correct.
Note: In this query you are getting any records where the COMP or SEW exists anywhere in the field. If you want it to show only when it is found at the start of the field it would be:
WHERE GL.Text LIKE & SomeData.TextFld & '*';
And likewise if you want it to only match where it is found at the end:
WHERE GL.Text LIKE '*' & SomeData.TextFld;

You should concatenate wild character at the end (or beginning, or both) of the field TextFld
WHERE GL.Text LIKE '%' + SomeData.TextFld + '%'

Related

Dynamic Selection Query with Criteria in Ms Access | SQL

I have a query in which I select multiple values. To create my form.
The results look like this :
the last Column [Candidat Nom] is a drop down list with an other query (lets call it Query 1) that select my drop down list values.
The selection is good and is what I'm looking for. Except I get the same value for all lines when they need to be different.
To simplify
let's take the following exemple
I have the following candidate that wants to join for the following job (Represented with their ID).
As we can see 2 candidates wants job N° 12. and 1 candidate for each other job.
What I get
All candidates are listed for every job.
What I want
What I actually did
is I put the following query (Query 1) on my column.
SELECT T_SALARIE.SALARIE_nom & " " & T_SALARIE.SALARIE_prenom AS Candidat Nom
FROM T_EMPLOI INNER JOIN (T_SALARIE INNER JOIN (T_SALARIE_EMPLOI LEFT JOIN T_STATUT_EMPLOI ON T_SALARIE_EMPLOI.SALARIE_EMPLOI_statut_id = T_STATUT_EMPLOI.STATUT_EMPLOI_id) ON T_SALARIE.SALARIE_NNI = T_SALARIE_EMPLOI.SALARIE_EMPLOI_salarie_nni) ON T_EMPLOI.EMPLOI_identifiant = T_SALARIE_EMPLOI.SALARIE_EMPLOI_emploi_identifiant
WHERE (((T_STATUT_EMPLOI.STATUT_EMPLOI_statut) Like "*valid*" Or (T_STATUT_EMPLOI.STATUT_EMPLOI_statut) Like "*décidé*") AND ((T_EMPLOI.EMPLOI_entreprise_id)=1));
This gave me the result I want but with the issue I mentioned previously (Same result for each line)
So
I thought I needed a new Criteria.
I added one, where It's going to select the candidate when the two "emploi ID" of my actual table (Shown before) and the one helping me select the candidates are equal.
With the following query:
SELECT T_SALARIE.SALARIE_nom & " " & T_SALARIE.SALARIE_prenom AS Candidat, T_SALARIE_EMPLOI.SALARIE_EMPLOI_emploi_identifiant
FROM T_EMPLOI INNER JOIN (T_SALARIE INNER JOIN (T_SALARIE_EMPLOI LEFT JOIN T_STATUT_EMPLOI ON T_SALARIE_EMPLOI.SALARIE_EMPLOI_statut_id = T_STATUT_EMPLOI.STATUT_EMPLOI_id) ON T_SALARIE.SALARIE_NNI = T_SALARIE_EMPLOI.SALARIE_EMPLOI_salarie_nni) ON T_EMPLOI.EMPLOI_identifiant = T_SALARIE_EMPLOI.SALARIE_EMPLOI_emploi_identifiant
WHERE (((T_STATUT_EMPLOI.STATUT_EMPLOI_statut) Like "*valid*" Or (T_STATUT_EMPLOI.STATUT_EMPLOI_statut) Like "*décidé*") AND ((T_SALARIE_EMPLOI.SALARIE_EMPLOI_emploi_identifiant)=[R_Select_COMOB]![ACTION_identifiant_emploi]));
But I keep on getting the following pop up that asks me to enter a Job ID
So how can I make the query for each line compare and select the right values?
I hope I was clear in explaining. If not please let me know so that I can add more details.
Thank you !
Thanks to your help and specially #June7 for his propositions, I found a solution regarding my problem :
I added a criteria to select values based on JobID that I wasn't selecting in the first hand.
And then based on the column (jobID) select the values needed
here is my final query :
SELECT
[SALARIE_nom] & " " & [SALARIE_prenom] & " (" & [SALARIE_NNI] & ")" AS Salarié, T_SALARIE_EMPLOI.SALARIE_EMPLOI_salarie_nni, T_SALARIE_EMPLOI.SALARIE_EMPLOI_id, T_SALARIE_EMPLOI.SALARIE_EMPLOI_emploi_identifiant
FROM
(T_STATUT_EMPLOI INNER JOIN T_SALARIE_EMPLOI ON T_STATUT_EMPLOI.STATUT_EMPLOI_id = T_SALARIE_EMPLOI.SALARIE_EMPLOI_statut_id) LEFT JOIN R_Select_Salarie ON T_SALARIE_EMPLOI.SALARIE_EMPLOI_salarie_nni = R_Select_Salarie.SALARIE_NNI
WHERE
(((T_SALARIE_EMPLOI.SALARIE_EMPLOI_emploi_identifiant)=[Formulaires]![F_COMOB]![ACTION_identifiant_emploi]) AND ((T_STATUT_EMPLOI.STATUT_EMPLOI_statut) Like "*validé*") AND ((T_SALARIE_EMPLOI.SALARIE_EMPLOI_Entreprise) Like "*RTE*"));
And Then to update my values for each line. I added a VBA code that requery on input.
Private Sub ACTION_Candidats_P_Enter()
ACTION_Candidats_P.Requery
End Sub
With that my problem is solved.

Pull back specific post codes from table in SQL

I'm having an issue in selecting specific post codes.
These are all valid UK post code formats:
WV11JX
WV1 1JX
WV102QK
WV10 2QK
WV113KQ
WV11 3KQ
Now, say I had a mix of the above formats in the data table; I'm trying to select only post codes that conform to the WV1 prefix (in this example).
In the above 6 item list, I'd want to return:
WV11JX
WV1 1JX
I would want to exclude:
WV102QK
WV10 2QK
WV113KQ
WV11 3KQ
If I execute the following query this will bring back both the WV11's and the WV1's:
SELECT ad.PostCode,*
FROM Staff st
INNER JOIN Address ad on ad.AddressID = st.Address
WHERE
ad.PostCode like 'WV1%'
Changing the condition in the WHERE to cater for length like this doesn't really work either:
SELECT ad.PostCode,*
FROM Staff st
INNER JOIN Address ad on ad.AddressID = st.Address
WHERE
(
ad.PostCode like 'WV1%'
OR
(ad.PostCode like 'WV1%' and LEN(ad.PostCode) = 6)
The above will just filter out any of the formats with a space so if we cater for those by doing the below:
SELECT ad.PostCode,*
FROM Staff st
INNER JOIN Address ad on ad.AddressID = st.Address
WHERE
(ad.PostCode like 'WV1%' and LEN(ad.PostCode) = 6)
or
(ad.PostCode like 'WV1 %' and LEN(ad.PostCode) = 7)
That fixes the issue but the problem is that we want to check more than just the 'WV1' prefix in this manner so having a growing list of 'OR' comparisons isn't viable.
How do we isolate the above post codes in a scalable way?
I'm using Microsoft SQL Server 2016.
I think the logic you want is:
WHERE ad.PostCode like 'WV1 [0-9][A-Z][A-Z]' OR
ad.PostCode like 'WV1[0-9][A-Z][A-Z]'
I'm not sure if numbers are allowed for the last three characters.

Ways to Clean-up messy records in sql

I have the following sql data:
ID Company Name Customer Address 1 City State Zip Date
0108500 AAA Test Mish~Sara Newa Claims Chtiana CO 123 06FE0046
0108500 AAA.Test Mish~Sara Newa Claims Chtiana CO 123 06FE0046
1802600 AAA Test Company Ban, Adj.~Gorge PO Box 83 MouLaurel CA 153 09JS0025
1210600 AAA Test Company Biwel~Brce 97kehst ve Jacn CA 153 04JS0190
AAA Test, AAA.Test and AAA Test Company are considered as one company.
Since their data is messy I'm thinking either to do this:
Is there a way to search all the records in the DB wherein it will search the company name with almost the same name then re-name it to the longest name?
In this case, the AAA Test and AAA.Test will be AAA Test Company.
OR Is there a way to filter only record with company name that are almost the same then they can have option to change it?
If there's no way to do it via sql query, what are your suggestions so that we can clean-up the records? There are almost 1 million records in the database and it's hard to clean it up manually.
Thank you in advance.
You could use String matching algorithm like Jaro-Winkler. I've written an SQL version that is used daily to deduplicate People's names that have been typed in differently. It can take awhile but it does work well for the fuzzy match you're looking for.
Something like a self join? || is ANSI SQL concat, some products have a concat function instead.
select *
from tablename t1
join tablename t2 on t1.companyname like '%' || t2.companyname || '%'
Depending on datatype you may have to remove blanks from the t2.companyname, use TRIM(t2.companyname) in that case.
And, as Miguel suggests, use REPLACE to remove commas and dots etc.
Use case-insensitive collation. SOUNDEX can be used etc etc.
I think most Database Servers support Full-Text search ability, and if so there are some functions related to Full-Text search that support Proximity.
for example there is a Near function in SqlServer and here is its documentation https://msdn.microsoft.com/en-us/library/ms142568.aspx
You can do the clean-up in several stages.
Create new columns
Convert everything to upper case, remove punctuation & whitespace, then match on the first 6 to 10 characters (using self join). Assuming your table is called "vendor": add two columns, "status", "dupstr", then update as follows
/** Populate dupstr column for fuzzy match **/
update vendor v
set v.dupstr = left(upper(regex_replace(regex_replace(v.companyname,'.',''),' ','')),6)
;
Identify duplicate records
Add an index on the dupstr column, then do an update like this to identify "good" records:
/** Mark the good duplicates **/
update vendor v
set v.status = 'keep' --indicate keeper record
where
--dupes to clean up
exists ( select 1 from vendor v1 where v.dupstr = v1.dupstr
and v.id != v1.id )
and
( --keeper has longest name
length(v.companyname) =
( select max(length(v2.companyname)) from vendor v2
where v.dupstr = v2.dupstr
)
or
--keeper has latest record (assuming ID is sequential)
v.id =
( select max(v3.id) from vendor v3
where v.dupstr = v3.dupstr
)
)
group by v.dupstr
;
The above SQL can be refined to add "dupe" status to other records , or you can do a separate update.
Clean Up Stragglers
Report any remaining partial matches to be reviewed by a human (i.e. dupe records without a keeper record)
You can use SQL query with SOUDEX of DIFFRENCE
For example:
SELECT DIFFERENCE ('AAA Test','AAA Test Company')
DIFFERENCE returns 0 - 4 ( 4 = almost the same, 0 - totally diffrent)
See also: https://learn.microsoft.com/en-us/sql/t-sql/functions/difference-transact-sql?view=sql-server-2017

SQL Server 2008 AND/OR operators and parentheses

I am having a bit of trouble with AND/OR operators. It's easy stuff, but I'm having trouble with the following scenario:
WHERE (ID = '111') OR (charge_desc LIKE '%garn%') OR
(charge_desc LIKE '%levy%') OR
(charge_desc LIKE '%exe%')
Basically, I am trying to find the keywords based only on ID 111. However, what's happening with the current query is that it looks for those keywords based on a bunch of different IDs instead. I've tried to manipulate the parenthesis, and I see the issue. Because it can't be "111 OR LIKE XYZ..." but it can't be AND either because if you do AND, then it looks for that ID based on EXACTLY those 3 criteria.
I am looking to do ID 111 and look for garn or levy or exe - not "AND" but it should be every variation that comes up but ONLY for 111.
I hope this makes sense. I feel its something with the parenthesis.
I just tried this:
WHERE ID = 111
HAVING garn or levy or exe
Forgive my lack of syntax there. :)
If you absolutely must have id = 111 then this is an and relationship, not an or relationship. You can then have a series of or operators between the other conditions:
WHERE ID = '111' AND
(charge_desc LIKE '%garn%' OR
charge_desc LIKE '%levy%' OR
charge_desc LIKE '%exe%')
The problem is with the parenthesis.
Let's look at this scenario:
WHERE (ID = '111') OR (charge_desc LIKE '%garn%') OR
(charge_desc LIKE '%levy%') OR
(charge_desc LIKE '%exe%')
You are saying where ID = 111 OR Charg_Desc like garn...etc.
WHERE (ID = '111') AND
(charge_desc LIKE '%garn%' OR
charge_desc LIKE '%levy%' OR
charge_desc LIKE '%exe%')
Now, you're saying WHERE ID = 111 AND the following conditional OR is applied to bring in the additional match. Remember, the match is in addition to the ID match.

how to i remove characheters from the prefix table and make sure only from the start of string are removed

I need to be able to strip the following prefixes from product codes as you see I have included a simple query while yes the below shows me the cm im not wanting i cant use replace as it code replace any instance of cm the prefixes are held in the supplire table cross refer with the products table
prefixes are not always two chrachters for example can be TOW
SELECT * , left(prod.productcode, LEN(sup.prefix)) AS MyTrimmedColumn
FROM MSLStore1_Products prod ,supplier sup
WHERE prod.suppid = 9039 AND prod.SgpID = 171
and sup.supno = prod.suppid
Product Codes:
ProductCode
CMDI25L
CMDI300M
CMDI750M
CMXFFP5L
Prefixes:
Prefix
CM
CM
CM
CM
You could use SUBSTRING() for that:
SUBSTRING(prod.productcode, LEN(sup.prefix))
(concrete syntax may vary for different database-managers)
You might want to put your prefixes in another table, and run the productCode field through a filtering UDF to retrieve the final code.
Something like
SELECT * , dbo.FilterPCode(prod.productcode) AS MyTrimmedColumn
FROM MSLStore1_Products prod ,supplier sup
WHERE prod.suppid = 9039 AND prod.SgpID = 171
and sup.supno = prod.suppid
then just define a UDF that takes a string product code and removes any prefix from the front.
You might see a performance hit using a UDF like this for really massive queries, and if that's the case, it might be better to generate a table of table of product codes without the prefix linked to the product codes with the prefix. Don't know enough about the data schema to know if that's truly possible without getting cross links though.
how do i thought use this query and imortant the results from that into the products table external code field
SELECT * , right(prod.productcode, len(prod.productcode) - LEN(sup.prefix) ) AS ExternalCoode
FROM MSLStore1_Products prod ,supplier sup
WHERE prod.suppid = 9217 AND prod.SgpID = 123 and sup.supno = prod.suppid