Parse Json in SQL Server - json

In my table, the value column contains json data. I am using parsejson to parse these values. I am using older version of SQL Server. So I am using parsejson:
id fieldid value
--------------------------------------------------------------------
1 70297 {"value":"Billable ","text":"Billable"}
2 70297 [{"value":"billable","text":"Billable"}]
3 70297 [{"value":"billable","text":"Billable"},
{"value":"nonbillable","text":"NonBillable"}]
4 70297 [{"value":" nonbillable","text":" NonBillable"}]
I need this output:
count stringvalue
--------------------
3 Billable
2 nonbillable
I am using this query to parse above json values from the table:
DECLARE #Names VARCHAR(8000)
SELECT #Names = COALESCE(#Names + ', ', '') + Value
FROM ValueBindings
WHERE fieldid = 70297
SELECT COUNT(*), StringValue
FROM parseJSON(#Names)
WHERE NAME IN ('value', 'text')
GROUP BY StringValue
SELECT #Names
It is not returning the expected values correctly

Modify your query like below to get the desired result
SELECT COUNT(*), RTRIM(LTRIM(StringValue))
FROM parseJSON(#Names)
WHERE NAME IN ('value')
GROUP BY RTRIM(LTRIM(StringValue))

try the following:
SELECT COUNT([NAME])/2 [COUNT], LTRIM(RTRIM(StringValue)) StringValue
FROM parseJSON(#Names)
WHERE NAME IN ('value', 'text') AND [NAME] IS NOT NULL
GROUP BY LTRIM(RTRIM(StringValue))
Thanks.

Related

match a number using regex for comma separated number

I have a string that contains number with separated by comma like below.
15,22,20,26,33,445,40,44,22,225,115,2
I want to know if a number say 15 is in that string or not.The problem is that 15 and 115 both are a match.Same for other number say 2, for this case 20 , 25, and 225 are match.For both cases only it should return if there is 15 or 2 in the string.I tried using like keyword but it's not working. It also return the rows with 115 or 20, 225, 222 whille matching 15 and 2 respectively. Can anyone suggest a regex pattern?
Update
I have a query like below where I was using like keyword, but I was getting wrong result for above reason.
SELECT DISTINCT A.id,A.title,A.title_hi,A.cId,B.id as cid1,A.report_type ,A.icon_img_url, A.created_at , A.news_date
FROM tfs_report_news A, tfs_commodity_master B
WHERE (',' + RTRIM(A.cId) + ',') LIKE ('%,' + B.id + ',%')
AND A.ccId = B.ccId AND A.`report_type`= "M"
AND A.isDeleted=0 AND A.isActive=1 AND B.isDeleted=0
AND B.status=1
AND A.news_date= (SELECT MAX(T.news_date)
FROM tfs_report_news T WHERE (',' + RTRIM(T.cId) + ',')
LIKE ('%,' + B.id + ',%'))
ORDER BY created_at desc, id desc limit 100;
Here tfs_report_news has the string 15,22,20,26,33,445,40,44,22,225,115,2 as column name cId and individual cId like 15 or 2 is id of tfs_commodity_master
In MySQL, what you asked for is the purpose of string function find_in_set():
Returns a value in the range of 1 to N if the string str is in the string list strlist consisting of N substrings. A string list is a string composed of substrings separated by , characters [...] Returns 0 if str is not in strlist or if strlist is the empty string. Returns NULL if either argument is NULL.
So to check if a value is present in the list, you can just do:
find_in_set('15', '15,22,20,26,33,445,40,44,22,225,115,2') > 0
Side note: here is a recommended reading.
Use FIND_IN_SET:
SELECT
CASE WHEN FIND_IN_SET('15', csv) > 0 THEN 'yes' ELSE 'no' END AS result
FROM yourTable;
Another option would be to use LIKE:
SELECT
CASE WHEN CONCAT(',', csv, ',') LIKE '%,15,%' THEN 'yes' ELSE 'no' END AS result
FROM yourTable;
Finally, you could also use REGEXP here:
SELECT
CASE WHEN csv REGEXP '[[:<:]]15[[:>:]]' THEN 'yes' ELSE 'no' END AS result
FROM yourTable;

passing json values in sql select statement

I am trying to pass the each line of json file to the SQL Select statement.How I can pass the values using python in iterative way
Json File contains following lines :
{"row_id":"1","a":"600","b":"hello","date":"2017-07-01","enabled":"TRUE","id":"234"}
{"row_id":"2","a":"650","b":"world","date":"2018-08-02","enabled":"FALSE","id":"456"}
{"row_id":"3","a":"700","b":"world","date":"2019-02-10","enabled":"FALSE","id":"789"}
I am trying to pass each line values to the sql statement.
Eg :
when row_id = 1 then it should pass the values of the respective line
Select * from xyz where a='600' and b='hello' and date ='2017-07-01';
when row_id =2 then then it should pass the values of the respective line
Select * from xyz where a='650' and b='world' and date ='2018-08-02';
when row_id =2 then then it should pass the values of the respective line
Select * from xyz where a='700' and b='world' and date ='2019-02-10';
Thank you
Assuming you are passing one JSON object at a time
Example
Declare #JSON varchar(max) ='{"row_id":"1","a":"600","b":"hello","date":"2017-07-01","enabled":"TRUE","id":"234"}'
SELECT *
From xyz
Where a = JSON_VALUE(#JSON, '$.a')
and b = JSON_VALUE(#JSON, '$.b')
and date = JSON_VALUE(#JSON, '$.date')

MysQL Update if a count condition is met

I have a table which consists of 5000 rows. I need SQL command that could update each row by removing all values in "(...)" if only one couple of () is found.
Basically, if I have a name in a row:
Name surname (extra info)
I need to remove "(extra info)" and leave only Name surname
But if there is no additional couple of ()
If there is a row
Name Surname(data) (extra info)
The script should not amend this name
In simple words, I need to update a name where is only one ( or ) symbol
Many thanks
can you try to find first '(' and substring to it ?
don't forget to use case for none ( in string
update userlogin
set fullname = case position('(' in FullName)
when 0
then fullname
else substring(Fullname,1,position('(' in FullName) - 1)
end
This is an implementation of my question. I used select to let me check the result before applying it to update request. The script shows a table of
3 columns: Id, Name, UpdatedName, where Name is what we have and UpdatedName what we will obtain
SELECT `Id`,`Name`,
(case when ((LENGTH(`Name`)-LENGTH(REPLACE(`Name`, '(', ''))) = 1)
THEN
SUBSTRING_INDEX(`Name`, '(', 1)
ELSE
'-'
END)
as updated_name,
FROM table
WHERE (LENGTH(`Name`)-LENGTH(REPLACE(`Name`, '(', ''))) = 1
LIMIT 0,1500
P.S. I used Id to allow me to amend values
SELECT CASE
WHEN fname = 'correct' THEN 'your condition'
WHEN sname = 'correct' THEN 'your second condition'
ELSE 'baz'
END AS fullname
FROM `databasetable`
or you can do as like also
CASE
WHEN action = 'update' THEN
UPDATE sometable SET column = value WHERE condition;
WHEN action = 'create' THEN
INSERT INTO sometable (column) VALUES (value);
END CASE

Count flags for a variable (big) number of colums

I have a table which looks like this: http://i.stack.imgur.com/EyKt3.png
And I want a result like this:
Conditon COL
ted1 4
ted2 1
ted3 2
I.e., the count of the number of '1' only in this case.
I want to know the total no. of 1's only (check the table), neglecting the 0's. It's like if the condition is true (1) then count +1.
Also consider: what if there are many columns? I want to avoid typing expressions for every single one, like in this case ted1 to ted80.
Using proc means is the most efficient method:
proc means data=have noprint;
var ted:; *captures anything that starts with Ted;
output out=want sum =;
run;
proc print data=want;
run;
Try this
select
sum(case when ted1=1 then 1 else 0 end) as ted1,
sum(case when ted2=1 then 1 else 0 end) as ted2,
sum(case when ted3=1 then 1 else 0 end) as ted3
from table
In PostgreSQL (tested with version 9.4) you could unpivot with a VALUES expression in a LATERAL subquery. You'll need dynamic SQL.
This works for any table with any number of columns matching any pattern as long as selected columns are all numeric or all boolean. Only the value 1 (true) is counted.
Create this function once:
CREATE OR REPLACE FUNCTION f_tagcount(_tbl regclass, col_pattern text)
RETURNS TABLE (tag text, tag_ct bigint)
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE (
SELECT
'SELECT l.tag, count(l.val::int = 1 OR NULL)
FROM ' || _tbl || ', LATERAL (VALUES '
|| string_agg( format('(%1$L, %1$I)', attname), ', ')
|| ') l(tag, val)
GROUP BY 1
ORDER BY 1'
FROM pg_catalog.pg_attribute
WHERE attrelid = _tbl
AND attname LIKE col_pattern
AND attnum > 0
AND NOT attisdropped
);
END
$func$;
Call:
SELECT * FROM f_tagcount('tbl', 'ted%');
Result:
tag | tag_ct
-----+-------
ted1 | 4
ted2 | 1
ted3 | 2
The 1st argument is a valid table name, possibly schema-qualified. Defense against SQL-injection is built into the data type regclass.
The 2nd argument is a LIKE pattern for the column names. Hence the wildcard %.
db<>fiddle here
Old sqlfiddle
Related:
Select columns with particular column names in PostgreSQL
SELECT DISTINCT on multiple columns

Oracle 10g SQL regexp like

I'd like to ask if it's possible in a regexp to identify in a given number if there are 3 instances of a set.
For instance:
123456141414
123456171717
in the example above we have 3x14 and 3x17 so it should return the numbers in the regexp_like query.
But it should return all occurrences of 3 times the same numbers.
Please try this:
SELECT INPUT_TEXT, REGEXP_SUBSTR(INPUT_TEXT, '([[:digit:]]{2})\1\1', 6) EXTRACTED
FROM MY_TABLE
WHERE REGEXP_INSTR(INPUT_TEXT, '([[:digit:]]{2})\1\1', 6) > 0
Input table values:
INPUT_TEXT
--------------
123456141414
123456171717
123456111111
141414123456
123456121234
Query result:
INPUT_TEXT EXTRACTED
-------------- --------------
123456111111 111111
123456141414 141414
123456171717 171717
If I read your updated requirements correctly, you're checking that you have six digits followed by a pair of digits repeated three times. In which case, Reza's response should be modified to:
select * from (
select '123456343434' str from dual union all
select '123456555555' str from dual union all
select '1234565555550' str from dual union all
select '123456232324' str from dual union all
select '123456111110' str from dual )
where regexp_like(str,'^([[:digit:]]{6})([[:digit:]]{2})\2\2$')
which gives:
STR
123456343434
123456555555
Editted to add - if you want to extract the actual digit-pair that's repeated:
select regexp_replace(str,'^([[:digit:]]{6})([[:digit:]]{2})\2\2$','\2') result
from (
select '123456343434' str from dual union all
select '123456555555' str from dual union all
select '123456555555a' str from dual union all
select '123456232324' str from dual union all
select '123456111110' str from dual )
where regexp_like(str,'^([[:digit:]]{6})([[:digit:]]{2})\2\2$')