I have hundreds of phone number of the world. Each has its country prefix (the prefix varies: some are 1, 2, 3 or 4 digit long) + the phone number. I want to write a mysql query, which will show me the Country name by using the prefix.
Example : If i use sub-string for the first 3 digits, its working fine. But how i can show the prefixes which are 2 or 4 digit long ?
SELECT(
CASE (SUBSTR(Number,1,3))
WHEN '998' Then 'Uzbekistan '
WHEN '996' Then 'Kyrgyzstan '
WHEN '995' Then 'Georgia '
.....
....
ELSE 'OTHERS' END ) AS Country
A simple solution is based on the fact that the CASE statement is evaluated sequentially.
SELECT(
CASE
WHEN SUBSTR(Number,1,2) = '23' Then 'Try For 23 '
WHEN SUBSTR(Number,1,3) = '998' Then 'Uzbekistan '
WHEN SUBSTR(Number,1,3) = '996' Then 'Kyrgyzstan '
WHEN SUBSTR(Number,1,3) = '995' Then 'Georgia '
.....
....
ELSE 'OTHERS' END ) AS Country
Related
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;
I wish to extract only a number if it's between 8 and 12 digits long, otherwise I wish it to be a blank. However in the column of data there can be text which I want as a blank.
Have tried may alterations of the code below with different brackets, though I get an error
SELECT CASE WHEN
isnumeric(dbo.worksheet_pvt.MPRNExpected) = 0 THEN '' ELSE(
CASE WHEN(
len(dbo.worksheet_pvt.MPRNExpected) >= 8
AND len(dbo.worksheet_pvt.MPRNExpected) < 13
) THEN dbo.worksheet_pvt.MPRNExpected ELSE ''
END
) AS [ MPRN Expected ]
Assuming you are using SQL Server, I would suggest:
select (case when p.MPRNExpected not like '%[^0-9]%' and
len(p.MPRNExpected) between 8 and 12
then p.MPRNExpected
end) as MPRN_Expected
. . .
from dbo.worksheet_pvt p
Presumably, you don't want isnumeric(), because it allows characters such as '.', '-', and 'e' in the "number".
The problem with your code is that you have two case expressions and they are not terminated correctly.
As a note, in MySQL, you would use regular expressions:
select (case when p.MPRNExpected regexp '^[0-9]{8-12}$'
then p.MPRNExpected
end) as MPRN_Expected
. . .
from dbo.worksheet_pvt p
Try this query
SELECT CASE WHEN ISNUMERIC(COLUMN_NAME)=0 THEN '' ELSE
CASE WHEN (LEN(COLUMN_NAME)>=8 AND LEN(COLUMN_NAME)<13)
THEN COLUMN_NAME ELSE ''END END AS data FROM TABLE_NAME
Thanks.
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
I need to find the frequency of a string in a column, irrespective of its case and any white spaces.
For example, if my string is My Tec Bits and they occur in my table like this, as shown below :
061 MYTECBITS 12123
102 mytecbits 24324
103 MY TEC BITS 23432
247 my tec bits 23243
355 My Tec Bits 23424
454 My Tec BitS 23432
Then, the output should be 6, because, with whites pace removed and irrespective of case, all those strings are identical.
Is there any grep() equivalent in SQL as there is in R?
If your concern is only with the SPACE and the CASE, then you need two functions:
REPLACE
UPPER/LOWER
For example,
SQL> WITH DATA AS(
2 SELECT 'MYTECBITS' STR FROM DUAL UNION ALL
3 SELECT 'mytecbits' STR FROM DUAL UNION ALL
4 SELECT 'MY TEC BITS' STR FROM DUAL UNION ALL
5 SELECT 'my tec bits' STR FROM DUAL UNION ALL
6 SELECT 'MY TEC BITS' STR FROM DUAL UNION ALL
7 SELECT 'MY TEC BITS' STR FROM DUAL
8 )
9 SELECT UPPER(REPLACE(STR, ' ', '')) FROM DATA
10 /
UPPER(REPLA
-----------
MYTECBITS
MYTECBITS
MYTECBITS
MYTECBITS
MYTECBITS
MYTECBITS
6 rows selected.
SQL>
Then, the output should be 6
So, based on that, you need to use it in the filter predicate and COUNT(*) the rows returned:
SQL> WITH DATA AS(
2 SELECT 'MYTECBITS' STR FROM DUAL UNION ALL
3 SELECT 'mytecbits' STR FROM DUAL UNION ALL
4 SELECT 'MY TEC BITS' STR FROM DUAL UNION ALL
5 SELECT 'my tec bits' STR FROM DUAL UNION ALL
6 SELECT 'MY TEC BITS' STR FROM DUAL UNION ALL
7 SELECT 'MY TEC BITS' STR FROM DUAL
8 )
9 SELECT COUNT(*) FROM DATA
10 WHERE UPPER(REPLACE(STR, ' ', '')) = 'MYTECBITS'
11 /
COUNT(*)
----------
6
SQL>
NOTE The WITH clause is only to build the sample table for demonstration purpose. In our actual query, remove the entire WITH part, and use your actual table_name in the FROM clause.
So, you just need to do:
SELECT COUNT(*) FROM YOUR_TABLE
WHERE UPPER(REPLACE(STR, ' ', '')) = 'MYTECBITS'
/
You could use something like
UPPER(REPLACE(userString, ' ', ''))
to check for upper case only and to remove white space.
You could cast your statements to LOWER() before comparing them eg.
LOWER(column_name) = LOWER(variable)
more specific:
LOWER(First_name) = LOWER('JoHn DoE')
would become first name = 'john doe'
For the spacing you should use replace, the format for that is:
REPLACE(yourstring, ' ' , '')
' ' = a space character replace it by an empty string = ''
So you would do
WHERE LOWER(REPLACE(fieldname, ' ', '') = 'mytecbits'
You need to use count to bring back the number affected, Lower will place the data into lower case so that when you make a comparison you can make it lower case.
To remove spaces you then use Replace and replace the space with an empty string for your comparison:
Select COUNT(ColumnA)
from table
where Lower(Replace(ColumnB, ' ', '')) = 'mytecbits'
If you are looking for the number of instances of one specific string, irrespective of case / whitespace, then you need to do the following -
ignore whitespace
ignore case
count the number of instances of the string
So you want a query like the following -
SELECT
COUNT(field)
FROM
table
WHERE
UPPERCASE(REPLACE(field, ' ', '')) = UPPERCASE(REPLACE(userstring, ' ', ''))
This counts the number of rows in your table where field is the same as the userstring, when case is ignored (all set to the same case using UPPERCASE, so it is effecitvely ignored), and spaces are ignored (spaces are removed from the field and the userstring using REPLACE)
Since REGEXP is case insensitive, you can obtain a match by making the spaces optional, example:
SELECT count(field) FROM yourtable WHERE field REGEXP "MY *TEC *BITS";
Note: if needed, you can add a space or a [[:<:]] (word boundary) before "MY" and a space or a [[:>:]] after "BITS" to avoid false positive.
I have some questions about SQL 2K8 integrated full-text search.
Say I have the following tables:
Car with columns: id (int - pk), makeid (fk), description (nvarchar), year (int), features (int - bitwise value - 32 features only)
CarMake with columns: id (int - pk), mfgname (nvarchar)
CarFeatures with columns: id (int - 1, 2, 4, 8, etc.), featurename (nvarchar)
If someone searches "red honda civic 2002 4 doors", how would I parse the input string so that I could also search in the "CarMake" and "CarFeatures" tables?
Trying to parse search criteria like that will be a pain. A possible alternate solution would be to create a view that creates a long description of the car and create a full text index on that. So that view might look like:
Create View dbo.CarData
WITH SCHEMABINDING
As
Select dbo.Cars.Id
, dbo.CarMake.Manufactuer
+ ' ' + dbo.Cars.[Year]
+ Coalesce(' ' + dbo.Cars.Description,'')
+ ' ' + Case When Features & 1 <> 0 Then (Select Name From dbo.CarFeature Where Id = 1) Else '' End
+ ' ' + Case When Features & 2 <> 0 Then (Select Name From dbo.CarFeature Where Id = 2) Else '' End
+ ' ' + Case When Features & 4 <> 0 Then (Select Name From dbo.CarFeature Where Id = 4) Else '' End
+ ' ' + Case When Features & 8 <> 0 Then (Select Name From dbo.CarFeature Where Id = 8) Else '' End
+ ' ' + Case When Features & 16 <> 0 Then (Select Name From dbo.CarFeature Where Id = 16) Else '' End As Description
From dbo.Cars
Join dbo.CarMake
On CarMake.Id = Cars.MakeId
With a fulltext index on that view, then you might be able to take your search criteria and do:
Select ...
From CarData
Where Contains(Description, Replace('red honda civic 2002 4 doors', ' ', ' AND '))
Now, this is far from perfect. For example, it will result in '...4 AND doors' and thus find car models in 2004 with 2 doors or 4WD and 2 doors. In addition, I did not see color in your schema so I'm not sure how that would get into the mix.
It would obviously be substantially simpler to force the user to break up the search criteria into its constituent pieces instead of trying to implement a Google-like search. Thus, you would restrict the user to selecting the color from a drop list, selecting the make from another drop list and so on. If you did this, then you wouldn't need the above mentioned View and could instead query against the columns in the tables.
Btw, the features column being a bitwise value makes searches more of a pain as you will need to do a bitwise AND operation on each value to determine if it has the feature in question. It would be better to break out the Feature to Car mapping into a separate table.