I am using PowerShell and MS Access.
I would like to apply a math factor to what is inside the pipes in this column value.
Ex. -100.0 must become -400.0 and 100.0 must become 400.0, given the factor is 4.
I only need to modify "Min_Value" and "Max_Value" tokens (hard coded).
FiledValue comes from the database (there are multiple rows).
FieldValue isn't always exactly the same as this example, BUT the token pattern is always the same Ex. Min_Value=|.....|
function Test
{
$Factor = 4
# Hard-coded SQL query result
$FieldValue = "Min_Value=|-100.0|;Max_Value=|100.0|;COMM_ID1=|1|;"
# Compare this value with a regular expression (Issue A: This doesn't work because of the minus sign and decimal)
if ($FieldValue -match "Min_Value=\|([0-9]+)\|;Max_Value=\|([0-9]+)\|;")
{
# Trying to retreive -100.0 here...(Issue B: this doesn't work). I beleive I can only specify ||, not Min_Value=||
$TokenMinValue = $FieldValue.Split('Min_Value=||')[1]
$TokenMaxValue = $FieldValue.Split('Max_Value=||')[1]
# Trying to take the token (-100.0), multiply it by 4 and write it back where I found it (Issue C: this obvioulsy doesn't work)
$Result = $FieldValue -replace "$regex",($TokenMinValue * $Factor)
$Result = $FieldValue -replace "$regex",($TokenMaxValue * $Factor)
#The goal is for $Result to equal "Min_Value=|-400.0|;Max_Value=|400.0|;COMM_ID1=|1|;"
}
}
You didn't specify your DBMS so here's a solution using Postgres. At least you can follow the logic behind it:
select
concat(
replace(
concat('Min_Value=|', string_agg(intval,';')), ';', '|;Max_Value=|'),
'|;')
from (
select (unnest(regexp_matches('Min_Value=|10|;Max_Value=|100|;', 'Min_Value=\|([0-9]+)\|;Max_Value=\|([0-9]+)\|;'))::int*4)::TEXT as intval
) foo;
The magic happens like that:
with regexp_matches extract two integers from input string
use unnest to unpack the array into two separate rows
cast those integer values (which are text at the moment) to Integer and multiply by factor 4
use string_agg with ; as delimiter to make one string row containing both integers delimited with ;
use concat to append Min_Value=| at the beginning, so the string is now Min_Value=|40;400
use replace and replace ; with next part - |;Max_Value=| so the string is now Min_Value=|40|;Max_Value=|400
use concat again to append |; to the end of the string
Input:
Min_Value=|10|;Max_Value=|100|;
Result:
Min_Value=|40|;Max_Value=|400|;
Related
I have 2 columns that look a little like this:
Column A
Column B
Column C
ABC
{"ABC":1.0,"DEF":24.0,"XYZ":10.50,}
1.0
DEF
{"ABC":1.0,"DEF":24.0,"XYZ":10.50,}
24.0
I need a select statement to create column C - the numerical digits in column B that correspond to the letters in Column A. I have got as far as finding the starting point of the numbers I want to take out. But as they have different character lengths I can't count a length, I want to extract the characters from the calculated starting point( below) up to the next comma.
STRPOS(Column B, Column A) +5 Gives me the correct character for the starting point of a SUBSTRING query, from here I am lost. Any help much appreciated.
NB, I am using google Big Query, it doesn't recognise CHARINDEX.
You can use a regular expression as well.
WITH sample_table AS (
SELECT 'ABC' ColumnA, '{"ABC":1.0,"DEF":24.0,"XYZ":10.50,}' ColumnB UNION ALL
SELECT 'DEF', '{"ABC":1.0,"DEF":24.0,"XYZ":10.50,}' UNION ALL
SELECT 'XYZ', '{"ABC":1.0,"DEF":24.0,"XYZ":10.50,}'
)
SELECT *,
REGEXP_EXTRACT(ColumnB, FORMAT('"%s":([0-9.]+)', ColumnA)) ColumnC
FROM sample_table;
Query results
[Updated]
Regarding #Bihag Kashikar's suggestion: sinceColumnB is an invalid json, it will not be properly parsed within js udf like below. If it's a valid json, js udf with json key can be an alternative of a regular expression. I think.
CREATE TEMP FUNCTION custom_json_extract(json STRING, key STRING)
RETURNS STRING
LANGUAGE js AS """
try {
obj = JSON.parse(json);
}
catch {
return null;
}
return obj[key];
""";
SELECT custom_json_extract('{"ABC":1.0,"DEF":24.0,"XYZ":10.50,}', 'ABC') invalid_json,
custom_json_extract('{"ABC":1.0,"DEF":24.0,"XYZ":10.50}', 'ABC') valid_json;
Query results
take a look at this post too, this shows using js udf and with split options
Error when trying to have a variable pathsname: JSONPath must be a string literal or query parameter
I have a column in my Postgres database that stores jsonb type values. Some of these values are raw strings (not a list or dictionary). I want to be able to perform a regex search on this column, such as
select * from database where jsonb_column::text ~ regex_expression.
The issue is that for values that are already strings, converting from jsonb to text adds additional escaped double quotes at the beginning and end of the value. I don't want these included in the regex query. I understand why Postgres does this, but if, say we assume all values stored in the jsonb field were jsonb strings, is there a work around? I know you can use ->> to get a value out of a jsonb dictionary, but can't figure out a solution for just jsonb strings on their own.
Once I figure out how to make this query in normal Postgres, I want to translate it into Peewee. However, any and all help with even just the initial query would be appreciated!
Just cast the json to text. Here is an example:
class Reg(Model):
key = CharField()
data = BinaryJSONField()
class Meta:
database = db
for i in range(10):
Reg.create(key='k%s' % i, data={'k%s' % i: 'v%s' % i})
# Find the row that contains the json string "k1": "v1".
expr = Reg.data.cast('text').regexp('"k1": "v1"')
query = Reg.select().where(expr)
for row in query:
print(row.key, row.data)
Prints
k1 {'k1': 'v1'}
To extract a plain string (string primitive without key name) from a JSON value (json or jsonb), you can extract the "empty path" like:
SELECT jsonb '"my string"' #>> '{}';
This also works for me (with jsonb but not with json), but it's more of a hack:
SELECT jsonb '"my string"' ->> 0
So:
SELECT * FROM tbl WHERE (jsonb_column #>> '{}') ~ 'my regex here';
I want to use LIKE operator in access 10 sql query with variable.
Example:
temporary variable var contains value bs
var = "bs"
I want to match every String that starts with value of temporary variable followed by zero or more numbers.
I am trying to fire the query:
select * from xyz where variety LIKE "#[tempvars]![var] + [0-9]*"
It is returning 0 records.
Thankz for the help.
You need to refer to your tempvar outside of the quotes, and use & for concatenation:
select * from xyz where variety LIKE "#" & [tempvars]![var] & "[0-9]*"
This will return all records where variety starts with a literal #, then whatever is in [tempvars]![var], then a number, and then any amount of characters.
You can check if that variety is available in your table or not. If that variety is available in your table then don't search with like operator and otherwise use like operator.
The Problem
I have a field that stores file keys, such as:
dev/application/document_type_name/document 12345-67890_123.pdf
I need to select the key without the number on the end so the value looks like:
dev/application/document_type_name/document 12345-67890_.pdf
Potential Strategy
It's been a while since I've done T-SQL but coming from the .NET side I think the general strategy would be:
Get the last index of an underscore character
Get the last index of the period character.
Replace the value between those two characters with a blank.
In C#, I think it would be something like:
var test = "dev/application/document_type_name/document 12345-67890_123.pdf"
var indexOfUnderscore = test.LastIndexOf("_");
var indexOfPeriod = test.LastIndexOf(".");
var textToReplace = subtring(indexOfUnderscore + 1, indexOfPeriod -1);
var output = test.Replace(textToReplace, String.Empty);
Notes:
Every key will have that Format
The length of the value between the underscore and the period may be different (could be 1, 12345, etc.
the end result should keep the underscore and period
Try
select left(#s,len(#s)-charindex('_',REVERSE(#s)))+'_.pdf'
where #s is your string.
Or if the file extension can change
select left(#s,len(#s)-charindex('_',REVERSE(#s))+1)
+ right(#s,charindex('.',REVERSE(#s)))
If I have a number (such as 88) and I want to perform a LIKE query in Rails on a primary ID column to return all records that contain that number at the end of the ID (IE: 88, 288, etc.), how would I do that? Here's the code to generate the result, which works fine in SQLLite:
#item = Item.where("id like ?", "88").all
In PostgreSQL, I'm running into this error:
PG::Error: ERROR: operator does not exist: integer ~~ unknown
How do I do this? I've tried converting the number to a string, but that doesn't seem to work either.
Based on Erwin's Answer:
This is a very old question, but in case someone needs it, there is one very simple answer, using ::text cast:
Item.where("(id::text LIKE ?)", "%#{numeric_variable}").all
This way, you find the number anywhere in the string.
Use % wildcard to the left only if you want the number to be at the end of the string.
Use % wildcard to the right also, if you want the number to be anywhere in the string.
Simple case
LIKE is for string/text types. Since your primary key is an integer, you should use a mathematical operation instead.
Use modulo to get the remainder of the id value, when divided by 100.
Item.where("id % 100 = 88")
This will return Item records whose id column ends with 88
1288
1488
1238872388
862388
etc...
Match against arbitrary set of final two digits
If you are going to do this dynamically (e.g. match against an arbitrary set of two digits, but you know it will always be two digits), you could do something like:
Item.where(["id % 100 = ?", last_two_digits)
Match against any set or number of final digits
If you wanted to match an arbitrary number of digits, so long as they were always the final digits (as opposed to digits appearing elsewhere in the id field), you could add a custom method on your model. Something like:
class Item < ActiveRecord
...
def find_by_final_digits(num_digits, digit_pattern)
# Where 'num_digits' is the number of final digits to match
# and `digit_pattern` is the set of final digits you're looking fo
Item.where(["id % ? = ?", 10**num_digits, digit_pattern])
end
...
end
Using this method, you could find id values ending in 88, with:
Item.find_by_final_digits(2, 88)
Match against a range of final digits, of any length
Let's say you wanted to find all id values that end with digits between 09 and 12, for whatever reason. Maybe they represent some special range of codes you're looking up. To do this you could do another custom method to use Postgres' BETWEEN to find on a range.
def find_by_final_digit_range(num_digits, start_of_range, end_of_range)
Item.where(["id % ? BETWEEN ? AND ?", 10**num_digits, start_of_range, end_of_range)
end
...and could be called using:
Item.find_by_final_digit_range(2, 9, 12)
...of course, this is all just a little crazy, and probably overkill.
The LIKE operator is for string types only.
Use the modulo operator % for what you are trying to do:
#item = Item.where("(id % 100) = ?", "88").all
I doubt it "works" in SQLite, even though it coerces the numeric types to strings. Without leading % the pattern just won't work.
-> sqlfiddle demo
Cast to text and use LIKE as you intended for arbitrary length:
#item = Item.where("(id::text LIKE ('%'::text || ?)", "'12345'").all
Or, mathematically:
#item = Item.where("(id % 10^(length(?)) = ?", "'12345'", "12345").all
LIKE operator does not work with number types and id is the number type so you can use it with concat
SELECT * FROM TABLE_NAME WHERE concat("id") LIKE '%ID%'