SQL Server - Contains Query - sql

Using SQL Server 2014 and the following data:
ID Address City State
1 55 Main St Dallas TX
2 4 Elm Blvd Cupertino CA
3 66 Walnut Miami FL
4 21 Main Ave Cupertino CA
I'm trying to use a contains query across multiple columns to find matches, but can't figure out the proper syntax. In this case, I have the query part:
CONTAINS ((Address, City, State), '"main" or "cupertino")
This returns rows #1, #2, & #4.
I can also try this:
CONTAINS ((Address, City, State), '"main" and "cupertino")
This doesn't return any rows.
What I'm trying to figure out though, is how I would return just row #4 using the search terms "main" and "cupertino" using a contains query.
So basically, I'm trying to do the following but with a contains query:
WHERE (Address LIKE '%main%' OR City LIKE '%main%' OR Zip LIKE '%main%') AND (Address LIKE '%cupertino%' OR City LIKE '%cupertino%' OR Zip LIKE '%cupertino%')
Thanks!

The expression is for CONTAINS() is computed on each each column independently (as you might have guessed). One solution is to try:
CONTAINS((Address, City, State), '"main"') AND
CONTAINS((Address, City, State), '"cupertino"')
The more conventional method is to add a computed column and use that for the indexing:
alter table t add acs as (Address + ' ' + City + ' ' + State) persisted;
Then build the index on that column.

Related

Filtering rows in bigquery based on user parameters

I have a following sample table:
Info
County
State
info1
Sonoma
California
info2
Fresno
California
info3
Lake
California
info5
Lake
Florida
I need to select say, Sonoma county from California and Lake county from Florida. I need to pass the needed counties and the needed states as list parameters so that they could be given as arguments to a script.
SELECT
ST_UNION_AGG(Info) as counties_info
FROM
`project.dataset.table`
WHERE
County IN UNNEST(#counties) AND
State IN UNNEST(#states)
This query will also give me the Lake county in California, how do I modify the script while still using the needed list parameters [#counties and #states]?
NOTE: I cannot check for individual states as the #states parameters can have any state in it.
I would recommend using structs for the parameters:
SELECT ST_UNION_AGG(t.Info) as counties_info
FROM `project.dataset.table` t
WHERE EXISTS (SELECT 1
FROM UNNEST(#county_states) cs
WHERE cs.county = t.county AND cs.state = t.state
);
You can simply use
select ...
from `project.dataset.table`
where (State, County) in unnest(#state_county_pairs)
above assumes that your #state_county_pairs parameter is an array of sate, county pairs - like in below script
declare state_county_pairs array<struct<State string, Country string>> ;
set state_county_pairs = [
struct('California' as State, 'Sonoma' as County),
struct('Florida', 'Lake')
];
select *
from `project.dataset.table`
where (State, County) in unnest(state_county_pairs)
with output (if applied to sample data in your question)
Obviously, then you can do whatever aggregation or other logic you need
I am not reusing your ST_UNION_AGG(Info) as counties_info because it makes no sense having in mind presented values of Info field, but I hope this was just for simplification purposes, so I am using just select * here
Meantime, below is example using real data with geo data type which applicable to use with ST_ functions
select st_union_agg(county_geom) as counties_geo
from `bigquery-public-data.utility_us.us_county_area`
join `bigquery-public-data.utility_us.us_states_area`
using (state_fips_code)
where (state_name, county_name) in unnest(#var_state_county_pairs)
with output that combines those two counties geo info and is visualized as below

Matching string removal from another column

I am working in SQL Server 2014. I have 2 columns in a table named Gallery Name and Address. Below is my sample data from this table.
Gallery Name Address
--------------------------------------------------------------
Boltelang Boltelang street 12, Paris
BERG Contemporary BERG Contemporary gorge ave, New York
Like this, I have a total of 207 records. Now the issue is that the data of column Gallery Name is being repeated in address column which I want to remove from address column. So it should be like this in
Gallery Name Adress
--------------------------------------------
Bltelang street 12, Paris
BERG Contemporary gorge ave, New York
I have no clue which function I can use in SQL Server to achieve this
Answer to your query is to use REPLACE like following.
UPDATE TABLE_NAME
SET [Address] = REPLACE([Address], [Gallery Name],'')
Note: In above query, REPLACE will replace all the occurrences of [Gallery Name] in [Address].
There can be scenario where you need to replace only the first occurance, not if it exists somewhere in the middle. In that case you can try like following.
UPDATE T SET [Address]=
LTRIM(STUFF([Address], CHARINDEX([Gallery Name], [Address]), LEN([Gallery Name]), ''))
from TABLE_NAME T
WHERE [Address] LIKE [Gallery Name] +'%'
I would go for:
update t
set address = stuff(address, 1, len(gallery_name) + 1, '')
where address like gallery_name + ' %';
These cover the examples in your question, where the gallery name is at the beginning of the address followed by a space. I am very conservative in making such changes. If you have another pattern, then you can run another update to fix those.
You want to be careful using REPLACE(), in case the address repeats the gallery name:
New York New York 10 New York Ave
Assuming it's only needed when the "Gallery Name" is at the start of the "Address".
To correct the addresses in the table
UPDATE [YourTable]
SET [Address] = LTRIM(REPLACE([Address], [Gallery Name],''))
WHERE [Address] LIKE CONCAT([Gallery Name],'%')

columns manipulation in fast load

Hello i am new to teradata. I am loading flat file into my TD DB using fast load.
My data set(CSV FILE) contains some issues like some of the rows in city column contains proper data but some of the rows contains NULL. The values of the city columns which contains NULL are stored into the next column which is zip code and so on. At the end some of the rows contains extra columns due to the extra NULL in rows. Examples is given below. How to resolve these kind of issues in fastload? Can someone answer this with SQL example?
City Zipcode country
xyz 12 Esp
abc 11 Ger
Null def(city's data) 12(zipcode's data) Por(country's data)
What about different approach. Instead of solving this in fast load, load your data to temporary table like DATABASENAME.CITIES_TMP with structure like below
City | zip_code | country | column4
xyz | 12 | Esp |
NULL | abc | 12 | Por
In next step create target table DATABASENAME.CITY with the structure
City | zip_code | country |
As a final step you need to run 2 INSERT queries:
INSERT INTO DATABASENAME.CITY (City, zip_code, country)
SELECT City, zip_code, country FROM DATABASENAME.CITIES_TMP
WHERE CITY not like 'NULL'/* WHERE CITY is not null - depends if null is a text value or just empty cell*/;
INSERT INTO DATABASENAME.CITY (City, zip_code, country)
SELECT Zip_code, country, column4 FROM DATABASENAME.CITIES_TMP
WHERE CITY like 'NULL' /* WHERE CITY is null - depends if null is a text value or just empty cell*/
Of course this will work if all your data looks exacly like in sample you provide.
This also will work only when you need to do this once in a while. If you need to load data few times a day it will be a litte cumbersome (not sure if I used proper word in this context) and then you should build some kind of ETL process with for example Talend tool.

sql create a field from a field

I need to run a query that would pull information from a field that has 2 types of data .
Field is address and has 123 avenue as data and bb#yahoo.com.
I need to make 2 fields one for email and one STaddress from table customer and field address?
anyone can i assis..
its access and vb query
I thought of this
Select customer.address from customer where address like "#"
but still i need to display the the data of address field to 2 different fields...
Here is the query that fetches the two different fields:
select iif(field like '*#*', field, NULL) as email,
iif(field like '*#*, NULL, field) as address
from t
The usage of like in Access is a bit different from other databases.
I would suggest that you create a view with this logic. If you actually want to modify the table, you will have to add columns and populate them with logic like the above.
Based on this question and your duplicate question, I understand your table has a field which includes both the street address and email address and you want to split those into separate fields.
So your table includes this ...
YourField
------------------------------
1234 ave willie haha#yahoo.com
123 avenue bb#yahoo.com
And you want this ...
YourField street_address email_address
------------------------------ --------------- --------------
1234 ave willie haha#yahoo.com 1234 ave willie haha#yahoo.com
123 avenue bb#yahoo.com 123 avenue bb#yahoo.com
If that is correct, you can use the InstrRev() function to determine the position of the last space in YourField. Everything before the last space is the street address; everything after is the email address.
SELECT
y.YourField,
Left(y.YourField, InstrRev(y.YourField, ' ') -1) AS street_address,
Mid(y.YourField, InstrRev(y.YourField, ' ') +1) AS email_address
FROM YourTable AS y;
You may need to add a WHERE clause to ensure the query only tries to evaluate rows which include your expected YourField value patterns.
Try something like this:
select *,
(case locate('#', address) when 0 then null else address) as email,
(case locate('#', address) when 0 then address else null) as street
from table;
You'd probably need to adjust the name of "locate" function - I'm not sure if it is the same in access database.
If you have a street address and then an email address in the same field, and want to split them, then use this.
We'll call your original field Addy, and the new fields Street & Email.
SELECT Left(Addy, InStrRev(Addy, " ", InStr(Addy, "#")) - 1) AS Street, mid(Addy, InStrRev(Addy, " ", InStr(Addy, "#")) + 1) AS Email.
What this does is look for the #, then go backwards and look for the first space. The first function takes every left of that space and calls it Street, while the second function takes everything to the right.
The function is really 3 functions nested together. To really understand what it's doing, I'll dissect it.
I = InStr(Addy, "#")
J = InStrRev(Addy, " ", I)
Street = Left(Addy,J-1)

SQL Server - copy data across tables , but copy the data only when it match with a specific column name

For example I got this 2 table
dbo.fc_states
StateId Name
6316 Alberta
6317 British Columbia
and dbo.fc_Query
Name StatesName StateId
Abbotsford Quebec NULL
Abee Alberta NULL
100 Mile House British Columbia NULL
Ok pretty straightforward , how do I copy the stateId over from fc_states to fc_Query, but match it with the StatesName, let say the result would be
Name StatesName StateId
Abee Alberta 6316
100 Mile House British Columbia 6317
Thanks, and both stateName column type is text
How about:
update fc_Query set StateId =
(select StateId from fc_states where fc_states.Name = fc_Query.StatesName)
That should give you the result you're looking for.
This is a different way than what Eddie did, I like MERGE for updates if they're not dead simple (like I wouldn't consider yours dead simple). So if you're bored/curious also try
WITH stateIds as
(SELECT name, MAX(stateID) as stID
FROM fc_states
GROUP BY name)
MERGE fc_Query
on stateids.name = fc_query.statesname
WHEN MATCHED THEN UPDATE
SET fc_query.stateid = convert(int, stid)
;
The first part, from "WITH" to the GROUP BY NAME), is a CTE, that creates a table-like thing - a name 'stateIds' that is good as a table for the immediately following part of the query - where there's guaranteed to be only one row per state name. Then the MERGE looks for anything in the fc_query with a matching name. And if there's a match, it sets it as you want. YOu can make a small edit if you don't want to overwrite existing stateids in fc_query:
WITH stateIds as
(SELECT name, MAX(stateID) as stID
FROM fc_states
GROUP BY name)
MERGE fc_Query
ON stateids.name = fc_query.statesname
AND fc_query.statid IS NOT NULL
WHEN MATCHED THEN UPDATE
SET fc_query.stateid = convert(int, stid)
;
And you can have it do something different to rows that don't match. So I think MERGE is good for a lot of applications. You need a semicolon at the end of MERGE statements, and you have to guarantee that there will only be one match or zero matches in the source (that is "stateids", my CTE) for each row in the target; if there's more than one match some horrible thing happens, Satan wins or the US economy falters, I'm not sure what, just never let it happen.