I found out that I have a character varaying column with mistakes in a database with over 4 millon records. It contains numbers. Each number has to have 12 digits, but for some reason a lot of those numbers ended up having 10 digits.
The good news is that the only thing I have to do, is prepend '55' to each cell that only has 10 digits and starts with the number '22', leaving the ones with 12 digits untouched.
My objective is this:
UPDATE
table
SET
column = CONCAT( '55', column )
WHERE
LENGTH( column ) = 10 AND column LIKE( '22%');
I am thinking of using this:
UPDATE
telephones
SET
telephone_number = CONCAT( '55', telephone_number )
WHERE
LENGTH( telephone_number ) = 10 AND telephone_number LIKE( '22%');
Am I doing it right? If not, what would be the correct way to do it
What if instead of a string the numbers were stored as big int, same rules apply, it is still 10 digits long which means the number is lower than 3.000.000.000 and bigger than 2.000.000.000? and they all need to be the same number starting with 55
The answer is: yes, that's right. You can play around with a sample database here on SQL Fiddle. That one uses the BIGINT type. Also see this one by #gmm, which uses the VARCHAR form. Both work just like you've described them using your original syntax.
Related
enter image description here
Hey I'm looking to do a query which allows me to see how many citties have starting phone number with number 6 and the other between 7-9
SELECT COUNT(Ciudad) AS "T.Fijos", Ciudad
FROM "BBDD.CLIENTES"WHERE Teléfono LIKE "9%"
GROUP BY Ciudad
that query only shows me phone number starting with 9 I need to do all in one query
Please try the following.
However, I wonder whether your FROM should in fact be FROM "BBDD"."CLIENTES". By wrapping the entire name in double-quotes in that way, you are saying that the table name is "BBBD.CLIENTES" and not specifying a schema.
Unfortunately I am unable to test this on SQLite, but it should be generally OK.
We can use a common table expression (CTE - the WITH... part) to create a temporary view of the data including a new column for the starting digit.
Then we can use CASE WHEN ... to check what the start digit is and return some text describing that digit.
WITH t
AS
(
SELECT Ciudad,
"Teléfono",
CAST(SUBSTR(Teléfono,1,1) AS integer) AS starting_digit
FROM "BBDD.CLIENTES"
)
SELECT Ciudad,
'Teléfono starts with ' ||
CASE
WHEN starting_digit = 6 THEN '6'
WHEN starting_digit BETWEEN 7 AND 9 THEN '7, 8 or 9'
ELSE 'something else'
END AS phone_start,
COUNT(*) AS count_of_phone_numbers
FROM t
GROUP BY 1, 2;
I have a column in my table with these values:
PING_TO_ME_20100828_Any87
TO_THESE_D_COLUMN_ENTRY_20200825
TO_THESE_D_20100829_COLUMN_ENTRY
201901_ARE_YOU_TRYING_TO_REACH47
ASK_TO_UOU_201008
I need to separate date values in a separate column.
My output should be:
20100828
20200825
20100829
201901
201008
Any help is very much appreciated.
You will (and already have) likely get comments about this telling you to fix your design. And while that is likely true...I won't try to pick apart why you are doing this, and I'll just give you the answer you came here for.
Your goal is to pick out either an 8 digit string of integers, or a 6 digit string of integers.
Here is one way you could do it:
SELECT x.y
, COALESCE(SUBSTRING(x.y, NULLIF(PATINDEX('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%', x.y), 0), 8)
, SUBSTRING(x.y, NULLIF(PATINDEX('%[0-9][0-9][0-9][0-9][0-9][0-9]%', x.y), 0), 6))
FROM (
VALUES ('PING_TO_ME_20100828_Any87'),
('TO_THESE_D_COLUMN_ENTRY_20200825'),
('TO_THESE_D_20100829_COLUMN_ENTRY'),
('201901_ARE_YOU_TRYING_TO_REACH47'),
('ASK_TO_UOU_201008')
) x(y)
Explanation:
Since you are looking for both 8 and 6 digit values, you need to check for the longer of the two first. So first I search for the occurrence of a string of 8 integers using:
NULLIF(PATINDEX('%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]%', x.y), 0)
This returns the first position of a string of 8 integers. The reason I wrap it in a NULLIF() is because if the value is not found, then PATINDEX will return 0.
I use NULLIF() to return NULL in that case, essentially indicating nothing was found. If you pass a NULL value to SUBSTRING() then it also returns NULL.
This is all just a nice way of "failing over" to the 6 character string check.
So there I do the same thing again:
NULLIF(PATINDEX('%[0-9][0-9][0-9][0-9][0-9][0-9]%', x.y), 0)
Except this time, I only repeat [0-9] six times. And again, I use the NULLIF() trick, so that it returns NULL if no string is found.
Throw that all into SUBSTRING() and COALESCE() and you've got a function that returns the results you're looking for.
Potential downsides
There are a couple down sides to this method.
It is not checking for a valid date, it's simply looking for a string of either 8 integers, or 6 integers. It could be 12345678 and it would still detect and return that.
If there are strings of integers longer than 8 digits, it will grab only the first 8 characters.
If there are multiple occurrences of 6 or 8 character integer strings...it will only return the first one.
There are much more robust ways you could write this, but it all depends on your data and what you need to do.
Other methods
Another way it could be done depending on which version of SQL Server you are using, is using STRING_SPLIT().
SELECT x.y, s.[value]
FROM (
VALUES ('PING_TO_ME_20100828_Any87'),('TO_THESE_D_COLUMN_ENTRY_20200825'),('TO_THESE_D_20100829_COLUMN_ENTRY'),('201901_ARE_YOU_TRYING_TO_REACH47'),('ASK_TO_UOU_201008')
) x(y)
CROSS APPLY (
SELECT [value]
FROM STRING_SPLIT(x.y, '_')
WHERE [value] LIKE '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
OR [value] LIKE '[0-9][0-9][0-9][0-9][0-9][0-9]'
) s
This method handles a couple of the downsides mentioned earlier. For example, it will ONLY return integer strings of length 6 or 8. It will also return ALL integer strings of length 6 or 8 and not just the first one.
And there's other ways to identify the strings as well, like using ISNUMERIC(x.[value]) or TRY_CONVERT(int, s.[value]).
It all depends on how you are using this code...if it's runs fast enough, and it's a one off script, then it really doesn't matter. If it's running for millions of records at a time, then yeah you should play around with other methods.
I have data like this
1234500010
1234500020
1234500021
12345600010
12345600011
123456700010
123456700020
123456710010
The pattern is
1-data(varian 3-7 digit number) + 2-data(any 3 digit number) + 3-data (any 2 digit number)
I want to create SQL to get 1-data only.
For example I want to get data 12345
I want the result only
1234500010
1234500020
1234500021
If I using "like",
select *
FROM data
where ID like '12345%' `
I will get all the data with 12345, 123456 and 1234567
If I using equal, I will only get one specific data.
Can I combine like and equal together to get result like what I want?
select * FROM data where data = '12345 + any 2-data(3 digit) + any 3-data(2 digit)'
Anyone can help?
Addition : Sorry if I didn't mention the data type and make some miss communication. The data type is in char. #Gordon answers and the others not wrong. It works for number and varchar. but not works for char type. Here I post some pic for char data type. Oracle specification for char data type is a fixed lenght. So if I input less than lenght the remain of it will be change into a space.
Thank you very much. Hope someone can help for this
Since your datatype is CHAR, Gordon's answer is not working for you. CHAR adds trailing spaces for the strings less than maximum limit. You could use TRIM to fix this as shown. But, you should preferably store numbers in the NUMBER type and not CHAR or VARCHAR2, which will create other problems sooner or later.
select *
from data
where trim(ID) like '12345_____';
I think you want:
select *
from data
where ID like '12345_____' -- exactly 5 _
Here is a rextester demonstrating the answer.
You really can't combine equality and LIKE. But you can use a regular expression to do this kind of searching, with the REGEXP_LIKE function:
SELECT *
FROM DATA
WHERE REGEXP_LIKE(ID, '^12345[0-9]{3}[0-9]{2}');
But if I understand correctly, for your 1-data you really want a 3 to 7 digit number:
SELECT *
FROM DATA
WHERE REGEXP_LIKE(ID, '^[0-9]{3,7}[0-9]{3}[0-9]{2}');
Oracle regular expression docs here
SQLFiddle here
Best of luck.
I think this gives you the solution you want,
create table data(ID number(15));
insert into data values(1234500010);
insert into data values(1234500020);
insert into data values(1234500021);
insert into data values(12345600010);
insert into data values(12345600011);
insert into data values(123456700010);
insert into data values(123456700020);
insert into data values(123456710010);
select * from data where ID like '12345_____'
// After 5_ underscore are exactly 5 , any 3 digits from 2-data(3 underscores) and 2 digits from 3-data(2 underscores)
You'll be getting(OUTPUT) :
ID
1234500010
1234500020
1234500021
3 rows returned in 0.00 seconds
Using SQL in PostgreSQL I need to select all the rows from my table called "crop" when the first digit of the integer numbers in column "field_id" is 7.
select *
from crop
where (left (field_id,1) = 7)
First, you know that the column is a number, so I would be inclined to explicitly convert it, no matter what you do:
where left(crop::text, 1) = '7'
where crop::text like '7%'
The conversion to text is simply to be explicit about what is happening and it makes it easier for Postgres to parse the query.
More importantly, if the value has a fixed number of digits, then I would suggest using a numeric range; something like this:
where crop >= 700000 and crop < 800000
This makes it easier for Postgres to use an index on the column.
Try with cast, like this:
select *
from crop
where cast(substring(cast(field_id as varchar(5)),1,1) as int) = 7
where 5 in varchar(5) you should put number how long is your integer.
I'm using SQL Server 2005 and have a column that contains serial numbers, which are nvarchar(50).
My problem is selecting max(serial_no) from the table. The serial numbers used to have a length of 7 only but new ones are now 15. Whenever I select the max, I get a result with a length of 7, which means that data is old. I also can't filter it to only select from records which have a length of 15 because then i'll miss some other data on my query.
Old serial numbers look like this...
'SNGD001'
..., and new ones look like this:
'SN14ABCD0000001'
Edit: I tried creating a dummy table without the old serial numbers (5 characters long), and I'm getting correct results.
As has been mentioned, your question is a bit hard to follow. If the max value could be either one of your old serial numbers or one of your new ones, I believe the following should do the trick:
SELECT MAX(RIGHT('0000000' + REVERSE(LEFT(REVERSE(YourTextColumn), PATINDEX('%[a-z]%', REVERSE(YourTextColumn)) - 1)), 7))
FROM YourTable
It finds the first non numeric character from the right keeping everything to the right of that. It then left zero pads the resulting numeric string to 7 characters and applies the MAX function.
Your question is a little tough to follow without good sample data to get a bearing on. I suggest for future, you show a few more examples of data to get better context, especially with sequencing. Now, your desire to get the MAX() of a "serial_no" from your table appears you need so you get detect the next sequential serial number to assign. However, your serial number appears to be a concatenation of a prefix string and then sequential. So, if I were to look at your brief data MIGHT HAVE BEEN along the lines of (last 3 digits are the sequential serializations)
SNGD001
SNGD002
SNGD003
...
SNGD389, etc...
and your new data with the last (last 7 digits are sequential serializations)
SN14ABCD0000001
SN14ABCD0000002
SN14ABCD0000003
...
SN14ABCD0002837
If this is correct, then you basically need to look at the max based on the leading 3 or 8 characters of the string PLUS the converted suffix numeric sequence. For starters, lets go with that to see if we are on the correct track or not, then you can easily concatenate the prefix and sequence number together at the end for determining the next available number.
So, based on the above samples, you may want to know that for each prefix, the last number of
SNGD389 and
SN14ABCD0002837 respective per their prefix
If the above is correct, I might start with...
select
case when LEN( RTRIM( yt.serial_no )) = 7
then LEFT( yt.serial_no, 4 )
else LEFT( yt.serial_no, 8 ) end as SerialPrefix,
MAX( case when LEN( RTRIM( yt.serial_no )) = 7
then CONVERT(INT, RIGHT( yt.serial_no, 3 ))
else CONVERT(INT, RIGHT( yt.serial_no, 7 )) end ) as SerialSequence
from
YourTable yt
group by
case when LEN( RTRIM( yt.serial_no )) = 7
then LEFT( yt.serial_no, 4 )
else LEFT( yt.serial_no, 8 ) end as SerialPrefix
Which would result in (based on sample data I presented)
SerialPrefix SerialSequence
SNGD 389
SN14ABCD 0002837
Of which since the serial sequence column being numeric, you could add 1 to it, then left-zero fill a string and concatenate the two back together such as to create
SNGD390
SN14ABCD0002838