Not selecting Max Value - sql

I am using the query
select max(entry_no) from tbl_Invmaster
but its giving me ans 9 however the max value is 10.

You probably have the numbers in a VARCHAR column. Ordering in those fields is by alphabetcal order. That way 9 is bigger than 10. Explanation from the link:
To determine which of two strings comes first in alphabetical order, their first letters are compared. If they differ, then the string whose first letter comes earlier in the alphabet is the one which comes first in alphabetical order. If the first letters are the same, then the second letters are compared, and so on. If a position is reached where one string has no more letters to compare while the other does, then the first (shorter) string is deemed to come first in alphabetical order.
Your best solution is not to store numbers in VARCHAR columns but instead use the appropriate type, eg INT. That way your query would return the correct result.
If that is not an option for you, you could CAST the column to an integer type. Eg in SQL Server you would write:
select max(CAST(entry_no AS INT)) from tbl_Invmaster

select max( to_number( entry_no )) from tbl_invmaster

Related

How to find letters in a string that contains mostly numbers in netezza

I have a field that is a string but should be mostly numbers. I need to be able to find if a letter is in this string. The letter can be in any spot in the string.
You can use:
select t.*
from t
where regexp_like(field, '[^0-9]');
That is, return any row where field has a non-digit.

Randomize integers in a string

I am attempting to randomize all integers in a string.
E.g "Transferred to account 123456789" randomized into "Transferred to account 256829876"
I already have a slow solution in PL/SQL where I am looping through each character in the string individually. If char is an asci value between 48-57 (digits 0 to 9), I randomize the digit accordingly.
In SQL I have gotten this far:
select regexp_replace('Transferred to account 05172262116','[0-9]',
floor(dbms_random.value(0, 10)))
from dual;
However, this does not give me the expected result as integers are replaced with a single unique value. (E.g. 'Transferred to account 555555555')
Is it possible to achieve what I am looking for via use of SQL?
Thanks.
If you know the numbers are always 11 digits, you can explicitly look for that:
select regexp_replace('Transferred to account 05172262116','[0-9]{11}', floor(dbms_random.value(10000000000, 99999999999)))
from dual;
Otherwise, you can replace with an integer, but the length may not be the same length as the original one:
select regexp_replace('Transferred to account 05172262116','[0-9]+', floor(dbms_random.value(10000000000, 99999999999)))
from dual;
As a note: things like account numbers are often removed using translate(), but this produces a fixed string:
select translate('Transferred to account 05172262116', ' 0123456789', ' ##########')
from dual;
(And you can do the same thing with regexp_replace().)
This answer may be viewed as a cop-out, but I would argue that information as sensitive as an account number should not be shown in any form, even if the digits are randomly permuted. So, I recommend just completely masking the account number using e.g.
SELECT
REGEXP_REPLACE('Transferred to account 05172262116', '[0-9]', '*')
FROM dual;
Even the above presents some security risk, because it shows the same number of * as there are digits in the account number. But, it is often the case, e.g. with credit cards or account numbers at a given bank, that all account numbers have the same length anyway.
The issue that you are having is that you are doing the replace once. This gets you one value to replace each character with. To do this correctly you would have to loop through each character and get a new random value to replace it with.
You could use translate() with a single 10-digit random number:
select translate('Transferred to account 05172262116',
'1234567890',
floor(dbms_random.value(1000000000, 10000000000))) from dual;
TRANSLATE('TRANSFERREDTOACCOUNT051
----------------------------------
Transferred to account 81677787668
It will work with any number of digits anywhere in the string, and preserves the original length (number of digits) of the replaced value. It maps an original digit to the same (random) digit each time, at least within that string. (If you apply the same translate across multiple source rows at one, they will get different mappings as dbms_random is non-deterministic).
with t (s) as (
select 'Transferred to account 05172262116' from dual
union all
select 'Transferred to account 05172262116' from dual
)
select s, translate(s,
'1234567890',
floor(dbms_random.value(1000000000, 10000000000))) from t;
S TRANSLATE(S,'1234567890',FLOOR(DBM
---------------------------------- ----------------------------------
Transferred to account 05172262116 Transferred to account 57238858225
Transferred to account 05172262116 Transferred to account 95587747554
Each digit in your original string is translated to the corresponding digit in the random number. For instance, the first output above came from the generated random number 6703187918. The first digit of you original string was 0; that's the 10th digit of the second argument to translate(); so you get the 10th digit of the (random) replacement string which is the third argument to that function - which is 8. The second digit in your string is 5, which is the 5th digit in the second argument; so you get the 5th digit in the third argument - which is 7. And so on.
It's arguable if this is random enough, I suppose, but the main goal is presumably to stop you reconstructing the original value from the replacement. You could potentially learn something about the shape of the original value by looking for repetitions new one; but as you could have repeated characters in the random value too that doesn't get you very far.
For instance, in the example above the replacement has a row of three consecutive 7s, so you might think the original has three consecutive digits too - but it didn't. The random value had two positions - 2nd and 7th - which both mapped to 7 in the new string, and you can't tell which of those mapping was applied. (So even if you knew the random value you couldn't get back to the original, in this case anyway - it won't always have repeated numbers, of course.)

MAX in SQLSERVER

This may be a small one but i could find any , see this is how it is..
I have a sqlserver table with two columns and two rows , one of the column's name is Number and it has two rows with values
1. c7df055e-f8b5-4fc5-9c0a-8f59624c4022
2. 1234
When i query the table with this query select max(Number) from table table_name
Its giving the result c7df055e-f8b5-4fc5-9c0a-8f59624c4022 , So how does MAX calculate the maximum value when any of the values contains characters, i have searched for this and found this
For character columns, MAX finds the highest value in the collating sequence.
But could understand better , so anyone please suggest a better explanation..
Thanks in advance
Collating sequence refers to the definition of how the numeric codes translate to characters. ASCII is a common collating sequence, for example; the byte "65" translates to the character "A", the byte "58" translates to the character "8" etc.
Most languages will compare character by character, comparing the underlying values. So "c" is 99 ASCII, and "1" is 49 ASCII, so the string starting with "c" will be the larger value. In general, lowercase letters are higher than upper case are higher than numbers, and other characters are all over the place.
Your "number" column is a text type (evidenced by presence of alpha and hyphen chars). For text types, sorting is alphabetic, and letters are "higher" than numbers, so the value starting with "c" is greater than one starting with "1".
Sorting has nothing to do with the format if the value: If the first character of the alphanumeric value was a zero, you would have got "1234" as the max.

How to do string manipulation in SQL query

I know I'm close to figuring this out but need a little help. What I'm trying to do is all grab a column from a particular table, but chop off the first 4 characters. For example if in a column the value is "KPIT08L", the result I was is 08L. Here is what I have so far but not getting the desired results.
SELECT LEFT(FIELD_NAME, 4)
FROM TABLE_NAME
First up, left will give you the leftmost characters. If you want the characters starting at a specific location, you need to look into mid:
select mid (field_name,5) ...
Secondly, if you value performance,portability and scalability at all, this sort of "sub-column" manipulation should generally be avoided. It's usually far easier (and faster) to patch columns together than to split them apart.
In other words, keep the first four characters in their own column and the rest in a separate column, and do your selects on the relevant one. If you're using anything less than a full column, then it's technically not one attribute of the row.
Try with
SELECT MID(FIELD_NAME, 5) FROM TABLE_NAME
Mid is very powerfull, it let you select the starting point and all the remainder, or,
if specified, the length desidered as in
SELECT MID(FIELD_NAME, 5, 2) FROM TABLE_NAME ' gives 08 in your example text
SELECT RIGHT(FIELD_NAME,LEN(FIELD_NAME)-4)
FROM TABLE_NAME;
If it is for a generic string then the above one will work...
Don't have Access at my current location, but please try this.
SELECT RIGHT(FIELD_NAME, LEN(FIELD_NAME)-4)
FROM TABLE_NAME
The LEFT(FIELD_NAME, 4) will return the first 4 caracters of FIELD_NAME.
What you need to do is :
SELECT MID(FIELD_NAME, 5)
FROM TABLE_NAME
If you have a FIELD_NAME of 10 caracters, the function will return the 6 last caracters (chopping the first 4)!

SQL String contains ONLY

I have a table with a field that denotes whether the data in that row is valid or not. This field contains a string of undetermined length. I need a query that will only pull out rows where all the characters in this field are N. Some possible examples of this field.
NNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNN
NNNNNEEEENNNNNNNNNNNN
NNNNNOOOOOEEEENNNNNNNNNNNN
Any suggestions on a postcard please.
Many thanks
This should do the trick:
SELECT Field
FROM YourTable
WHERE Field NOT LIKE '%[^N]%' AND Field <> ''
What it's doing is a wildcard search, broken down:
The LIKE will find records where the field contains characters other than N in the field. So, we apply a NOT to that as we're only interested in records that do not contain characters other than N. Plus a condition to filter out blank values.
SELECT *
FROM mytable
WHERE field NOT LIKE '%[^N]%'
I don't know which SQL dialect you are using. For example Oracle has several functions you may use. With oracle you could use condition like :
WHERE LTRIM(field, 'N') = ''
The idea is to trim out all N's and see if the result is empty string. If you don't have LTRIM, check if you have some kind of TRANSLATE or REPLACE function to do the same thing.
Another way to do it could be to pick length of your field and then construct comparator value by padding empty string with N. Perhaps something like:
WHERE field = RPAD('', field, 'N)
Oracle pads that empty string with N's and picks number of pad characters from length of the second argument. Perhaps this works too:
WHERE field = RPAD('', LENGTH(field), 'N)
I haven't tested those, but hopefully that give you some ideas how to solve your problem. I guess that many of these solutions have bad performance if you have lot of rows and you don't have other WHERE conditions to select proper index.