Remove String and Symbols - sql

I am trying to create a query to remove some varchar and symbols from a big string, basically a table will have a column with this format(the information comes from an API call):
$.owner = "javier#tl.com" and $.asignee ="joe" and $.Entities.Entity = "12345" And $.CountryService.Country ="1" and $.CountryService.Service="B"
so the requirement is to take the main "column names" from the sample, so at the end the string will be like:
owner = "javier#tl.com" and asignee ="joe" and Entity = "12345" And Country ="1" and Service="B"
this should be dynamic because we could have more data like $.Entities.Name, $.CountryService.Region, etc

This is rather simple and can be done leveraging STRING_SPLIT, STRING_AGG, and CHARINDEX.
DECLARE #string VARCHAR(1000) =
'$.owner = "javier#tl.com" and $.asignee ="joe" and $.Entities.Entity = "12345" And $.CountryService.Country ="1" and $.CountryService.Service="B"';
SELECT NewString =
STRING_AGG(SUBSTRING(split.value,IIF(p.P1>0 AND p.P2>p.P1,p.P1+1,1),8000),'and ')
FROM STRING_SPLIT(REPLACE(REPLACE(#string,'$.',''),'and ','|'),'|') AS split
CROSS APPLY (VALUES(CHARINDEX('.',split.value), CHARINDEX('"',split.value))) AS p(P1,P2);
Results:
owner = "javier#tl.com" and asignee ="joe" and Entity = "12345" and Country ="1" and Service="B"

Related

How can I insert data into this structure in BigQuery?

In BigQuery, I want to insert some data into this very simple data structure:
Field Type Mode
id STRING NULLABLE
policies RECORD REPEATED
s RECORD NULLABLE
something STRING NULLABLE
riskTypes RECORD REPEATED
code STRING NULLABLE
In the light of my previous question I would expect the syntax to be as follows:
UPDATE `tablename` SET policies = ARRAY_CONCAT(
policies, [
struct<s struct<something STRING, riskTypes ARRAY<struct<code STRING>>>
("example something", [("example description")])
]
)
WHERE id = 'Moose';
But this gives an error:
Unexpected "[" (before the "example description")
Below should work
update `tablename` set policies = policies || [
struct<s struct<something string, riskTypes array<struct<code string>> >>
(struct('example something' as something, [struct('example description 1' as code), struct('example description 2')]))
]
where id = 'Moose'

Active Record Query - Search Multiple Columns for Multiple Strings and Return Only if They Are All Included

I need help designing a query via Active Record & Postgresql.
• The query must search across all of the following columns...
The Model looks like this:
Collection
item_id1: String
item_id2: String
item_id3: String
item_id4: String
item_id5: String
item_id6: String
• The query needs to pass in an array of strings that need to be searched across all of the item_id fields.
• The query must also only return results of Records containing all of the strings within the array.
Note: I also have the Textacular Full Text Search gem installed. However, I tested a search that I believe is supposed to search and return matches only if the records include all of the passed in strings, and the search came up with nothing, despite records with those strings existing in my database. Like this: Collection.advanced_search('B0066AJ5TK&B0041KJSL2')
Just to clarify: You want records where each of the strings in the array are found somewhere within the six item_id fields?
There's probably a more elegant way to do this, but here's what I've got off the top of my head:
terms = ['foo', 'bar', 'baz']
conditions = []
values = {}
terms.each_with_index do |t,i|
arg_id = "term#{i}".to_sym
conditions << "(item_id1 = :#{arg_id} OR item_id2 = :#{arg_id} OR item_id3 = :#{arg_id} OR item_id4 = :#{arg_id} OR item_id5 = :#{arg_id} OR item_id6 = :#{arg_id})"
values[arg_id] = t
end
Collection.where(conditions.join(' AND '), values)
This should produce a query like this:
SELECT "collections".* FROM "collections" WHERE ((item_id1 = 'foo' OR item_id2 = 'foo' OR item_id3 = 'foo' OR item_id4 = 'foo' OR item_id5 = 'foo' OR item_id6 = 'foo') AND (item_id1 = 'bar' OR item_id2 = 'bar' OR item_id3 = 'bar' OR item_id4 = 'bar' OR item_id5 = 'bar' OR item_id6 = 'bar') AND (item_id1 = 'baz' OR item_id2 = 'baz' OR item_id3 = 'baz' OR item_id4 = 'baz' OR item_id5 = 'baz' OR item_id6 = 'baz'))
Which is long and ugly, but should get the results you want.
If you meant that the fields might contain the strings to be searched for, rather than be equal to them, you could instead use
item_id1 LIKE #{arg_id}
and
values[arg_id] = "%#{t}%"

retrieving values from a result set ruby sqllite

I ran a query as follows:
rs = conn.execute("SELECT * FROM fruits WHERE name = 'apple' AND type = 'sweet'" )
puts "Results = #{rs.inspect}"
this gives me something like
Results = [{"fruitId"=> 123, "name"=>"apple", "type"=>"sweet" }]
How do I get the fruitId out from this?
I tried this:
puts "Retrieved fruitId = #{rs['fruitId'] }"
But that results in an error:
[] no implicit conversion of string to integer
How can I get the fruitId out?
Thanks
You're getting back an array, but you want a hash to be able to use rs['fruitId']. That's what its complaining about.
Try doing this:
db = SQLite3::Database.open "test.db"
db.results_as_hash = true
Source:
http://zetcode.com/db/sqliteruby/queries/
http://www.ruby-doc.org/core-2.0/Hash.html
Its an Array of Hashes. You can access fruitId of the first item in the Array like this
Results[0]["fruitId"]
#=> 123

Multiple 'in' statements in a where clause that need to match against each other

I have a very long query that is essentially an extension of the following:
update property.lease_period
set scca_uplift = '110',
scca_notes_code = '21006'
where (suite_id = 'CCBG08' and lease_id = '205059')
or (suite_id = 'CCBG14' and lease_id = '152424')
or (suite_id = 'CCCF048' and lease_id = '150659')
The where clause for this will have ~40 rows when complete. In order to make this task easier I was hoping to do something similar to the following:
update property.lease_period
set scca_uplift = '110',
scca_notes_code = '21006'
where suite_id in('CCBG08', 'CCBG14', 'CCCF048')
and lease_id in('205059', '152424', '150659')
Unfortunately lease_id isn't a unique field and there can be multiple lease_id's to the same suite_id (so subsequently the second query is unusable).
Is there a better way to do the first update statement given that this solution won't work?
You may create table type and pass the values thru it, like that:
CREATE TYPE Suite_Lease AS TABLE
(
suite_id varchar(15) NOT NULL,
lease_id varchar(15) NOT NULL
)
GO
CREATE PROC DoUpdate
#Params Suite_Lease READONLY,
#uplift varchar(15),
#code varchar(15)
AS
update property.lease_period set
scca_uplift = #uplift,
scca_notes_code = #code
from property.lease_period tab
JOIN #params filt
on tab.suite_id=filt.suite_id AND tab.lease_id=filt.lease_id
This will keep your Procedure cache dry and clean, instead if you using multiple "big" where clauses
How to pass table parameter into stored procedure (c#):
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("suite_id", typeof (string)) {AllowDBNull = false, MaxLength = 15});
dt.Columns.Add(new DataColumn("lease_id", typeof (string)) {AllowDBNull = false, MaxLength = 15});
dt.Rows.Add("CCBG08", "205059");
... add more rows for match
using (var c = new SqlConnection("ConnectionString"))
{
c.Open();
using(var sc = c.CreateCommand())
{
sc.CommandText = "DoUpdate";
sc.CommandType = CommandType.StoredProcedure;
sc.Parameters.AddWithValue("#uplift", "110");
sc.Parameters.AddWithValue("#code", "21006");
sc.Parameters.Add(new SqlParameter("#Params", SqlDbType.Structured) { TypeName = null, Value = dt });
sc.ExecuteNonQuery();
}
}
Using the trick from this article. This looks a bit ugly, but it does the trick:
update property.lease_period
set scca_uplift = #uplift, scca_notes_code = #code
from property.lease_period tab
JOIN (
select 'CCBG08' as suite_id, '205059' as lease_id union all
select 'CCBG14', '152424' union all
select 'CCCF048', '150659'
) xxx
on tab.suite_id=xxx.suite_id AND tab.lease_id=xxx.lease_id
Try this
update property.lease_period
set scca_uplift = '110',
scca_notes_code = '21006'
where (suite_id in,lease_id) in
(select suite_id in,lease_id from XXX_table where CONDITION)
The last SELECT should give you those 40 combinations.
Derived from a comment by #dasblinkenlight (for Oracle) another possible way to do this would be the following:
select *
from property.lease_period
where (suite_id + ' ' + lease_id)
in (
('CCBG08 205059'),
('CCBG14 152424'),
('CCCF048 150659')
)
This isn't very recommended as it would be bad for indexing (concatenation on MicrosoftSQL) however I thought it was interesting all the same.
dasblinkenlights original comment:
#Michael I wish you were asking about Oracle, it's a lot cleaner
there: you do where (lease_period,lease_id) in
(('CCBG08','205059'),('CCBG14','152424'),('CCCF048','150659')), and it
does the trick. Why SQL Server couldn't do it is beyond me. –

How To Split Pipe-Delimited Column and insert each value into new table Once?

I have an old database with a gazillion records (more or less) that have a single tags column (with tags being pipe-delimited) that looks like so:
Breakfast
Breakfast|Brunch|Buffet|Burger|Cakes|Crepes|Deli|Dessert|Dim Sum|Fast Food|Fine Wine|Spirits|Kebab|Noodles|Organic|Pizza|Salad|Seafood|Steakhouse|Sushi|Tapas|Vegetarian
Breakfast|Brunch|Buffet|Burger|Deli|Dessert|Fast Food|Fine Wine|Spirits|Noodles|Pizza|Salad|Seafood|Steakhouse|Vegetarian
Breakfast|Brunch|Buffet|Cakes|Crepes|Dessert|Fine Wine|Spirits|Salad|Seafood|Steakhouse|Tapas|Teahouse
Breakfast|Brunch|Burger|Crepes|Salad
Breakfast|Brunch|Cakes|Dessert|Dim Sum|Noodles|Pizza|Salad|Seafood|Steakhouse|Vegetarian
Breakfast|Brunch|Cakes|Dessert|Dim Sum|Noodles|Pizza|Salad|Seafood|Vegetarian
Breakfast|Brunch|Deli|Dessert|Organic|Salad
Breakfast|Brunch|Dessert|Dim Sum|Hot Pot|Seafood
Breakfast|Brunch|Dessert|Dim Sum|Seafood
Breakfast|Brunch|Dessert|Fine Wine|Spirits|Noodles|Pizza|Salad|Seafood
Breakfast|Brunch|Dessert|Fine Wine|Spirits|Salad|Vegetarian
Is there a way one could retrieve each tag and insert it into a new table tag_id | tag_nm using MySQL only?
Here is my attempt which uses PHP..., I imagine this could be more efficient with a clever MySQL query. I've placed the relationship part of it there too. There's no escaping and error checking.
$rs = mysql_query('SELECT `venue_id`, `tag` FROM `venue` AS a');
while ($row = mysql_fetch_array($rs)) {
$tag_array = explode('|',$row['tag']);
$venueid = $row['venue_id'];
foreach ($tag_array as $tag) {
$rs2 = mysql_query("SELECT `tag_id` FROM `tag` WHERE tag_nm = '$tag'");
$tagid = 0;
while ($row2 = mysql_fetch_array($rs2)) $tagid = $row2['tag_id'];
if (!$tagid) {
mysql_execute("INSERT INTO `tag` (`tag_nm`) VALUES ('$tag')");
$tagid = mysql_insert_id;
}
mysql_execute("INSERT INTO `venue_tag_rel` (`venue_id`, `tag_id`) VALUES ($venueid, $tagid)");
}
}
After finding there is no official split function I've solved the issue using only MySQL like so:
1: I created the function strSplit
CREATE FUNCTION strSplit(x varchar(21845), delim varchar(255), pos int) returns varchar(255)
return replace(
replace(
substring_index(x, delim, pos),
substring_index(x, delim, pos - 1),
''
),
delim,
''
);
Second I inserted the new tags into my new table (real names and collumns changed, to keep it simple)
INSERT IGNORE INTO tag (SELECT null, strSplit(`Tag`,'|',1) AS T FROM `old_venue` GROUP BY T)
Rinse and repeat increasing the pos by one for each collumn (in this case I had a maximum of 8 seperators)
Third to get the relationship
INSERT INTO `venue_tag_rel`
(Select a.`venue_id`, b.`tag_id` from `old_venue` a, `tag` b
WHERE
(
a.`Tag` LIKE CONCAT('%|',b.`tag_nm`)
OR a.`Tag` LIKE CONCAT(b.`tag_nm`,'|%')
OR a.`Tag` LIKE CONCAT(CONCAT('%|',b.`tag_nm`),'|%')
OR a.`Tag` LIKE b.`tag_nm`
)
)