Counting a value in one cell - sql

I'm still new to SQL and I'm trying to figure out how to count the values within one cell.
Don't mind my Excel formula I was trying to calculate the data so I wouldn't have to go through SQL.
This is what I am coming up with, but it is counting the whole column and not the cell.
SELECT COUNT(Binlocation1) FROM BinLoc

Here's a solution in the Microsoft SQL Server dialect:
SELECT
-- Include any existing columns in the table.
*,
-- Calculate a new column: 'BinLocationQuantity'.
(DATALENGTH(BinLocation1) - DATALENGTH(REPLACE(BinLocation1, ', ', ''))) / DATALENGTH(', ') + 1
AS BinLocationQuantity
FROM BinLoc
The idea is to
Determine how much the ', ' separator contributes to the length of the text in the BinLocation1 field. We do this by taking the difference between (a) the length of the field, and (b) the length of the field when all occurrences of the separator are removed (REPLACEd with the empty '' string). Here we use DATALENGTH() rather than LEN(), to avoid confusion over whitespace.
Determine how many such separators there are. We do this by taking the total length (above) contributed by all the separators, and then dividing it by the length of a single separator: DATALENGTH(', ').
Extrapolate how many values are in the BinLocation1 text. We do this by adding 1 to the number (above) of separators:
-- 1 2 3 4 N + 1
'value1, value2, value3, value4, ..., valueN'
-- ^^ ^^ ^^ ^^
-- 1 2 3 N
Warning
The assumption must hold that each BinLocation1 text is of the form
'value1, value2, value3, value4'
and has neither any missing separators
'value1 value2, value3value4'
-- ^ ^
nor any extra separators:
', value1, value2, , value3, value4, '
-- ^^ ^^ ^^

Related

In SQL Server, how can I search for column with 1 or 2 whitespace characters?

So I need to filter column which contains either one, two or three whitespace character.
CREATE TABLE a
(
[col] [char](3) NULL,
)
and some inserts like
INSERT INTO a VALUES (' ',' ', ' ')
How do I get only the row with one white space?
Simply writing
SELECT *
FROM a
WHERE column = ' '
returns all rows irrespective of one or more whitespace character.
Is there a way to escape the space? Or search for specific number of whitespaces in column? Regex?
Use like clause - eg where column like '%[ ]%'
the brackets are important, like clauses provide a very limited version of regex. If its not enough, you can add a regex function written in C# to the DB and use that to check each row, but it won't be indexed and thus will be very slow.
The other alternative, if you need speed, is to look into full text search indexes.
Here is one approach you can take:
DECLARE #data table ( txt varchar(50), val varchar(50) );
INSERT INTO #data VALUES ( 'One Space', ' ' ), ( 'Two Spaces', ' ' ), ( 'Three Spaces', ' ' );
;WITH cte AS (
SELECT
txt,
DATALENGTH ( val ) - ( DATALENGTH ( REPLACE ( val, ' ', '' ) ) ) AS CharCount
FROM #data
)
SELECT * FROM cte WHERE CharCount = 1;
RETURNS
+-----------+-----------+
| txt | CharCount |
+-----------+-----------+
| One Space | 1 |
+-----------+-----------+
You need to use DATALENGTH as LEN ignores trailing blank spaces, but this is a method I have used before.
NOTE:
This example assumes the use of a varchar column.
Trailing spaces are often ignored in string comparisons in SQL Server. They are treated as significant on the LHS of the LIKE though.
To search for values that are exactly one space you can use
select *
from a
where ' ' LIKE col AND col = ' '
/*The second predicate is required in case col contains % or _ and for index seek*/
Note with your example table all the values will be padded out to three characters with trailing spaces anyway though. You would need a variable length datatype (varchar/nvarchar) to avoid this.
The advantage this has over checking value + DATALENGTH is that it is agnostic to how many bytes per character the string is using (dependant on datatype and collation)
DB Fiddle
How to get only rows with one space?
SELECT *
FROM a
WHERE col LIKE SPACE(1) AND col NOT LIKE SPACE(2)
;
Though this will only work for variable length datatypes.
Thanks guys for answering.
So I converted the char(3) column to varchar(3).
This seemed to work for me. It seems sql server has ansi padding that puts three while space in char(3) column for any empty or single space input. So any search or len or replace will take the padded value.

In SQL Server, how can I identify "double" strings and correct?

How can I find strings in a column that are doubled-up and correct them? I feel like there is an easy answer to this I just can't think of it.
Example:
I want to find instances of a repeating string, example "SolonSolon", and then update the column to "Solon".
Update:
They're always the same. No extra characters, but might have a space as part of the repeating value. Other examples would be...
"PlacePlace", "TreeTree", "OrangeOrange", "TravisMemorialHSTravisMemorialHS", "Texas HSTexas HS"
You can check if the string is equal to the first half replicated.
SELECT LEFT(YourCol,LEN(REPLACE(YourCol, ' ', 'x'))/2)
FROM YourTable
WHERE YourCol = REPLICATE(LEFT(YourCol,LEN(REPLACE(YourCol, ' ', 'x'))/2),2)
The reason for the REPLACE of spaces with x before calculating the LEN is because trailing spaces are ignored by this function. You can also use the technique in #lptr's answer for this but an edge case will be if the string was varchar(8000) and already 8000 characters long in which case concatenating an extra character won't do anything (LEN(SPACE(8000) + 'x') is 0).
..replace the first half of the value with an empty string..if there is nothing left..the value consists of two equal parts
select *, substring(c, 1, (len(c+'.')-1)/2)
from
(
values
('solosolo'), ('yoyo'), ('andand'), ('1212'),(' . .'),
('ababc'), ('onetwoone')
) as t(c)
where replace(c, substring(c, 1, (len(c+'.')-1)/2), '') = '';
Another alternative. The query removes inner spaces using REPLACE(str_col, ' ', ''), removes leading/traling spaces using TRIM, and checks to make sure the first half of the string equals the second half.
select left(no_spaces.str_col, v.str_len/2)
from foo f
cross apply (values (replaced trim(f.str_col), ' ', '')) no_spaces(str_col)
cross apply (values (len(no_spaces.str_col))) v(str_len)
where no_spaces.str_col=replicate(left(f.str_col, v.str_len/2), 2);

number format to char in oracle while creating a view

I have the below view:
CREATE OR REPLACE VIEW viewA ("col1", "col2") AS
SELECT DISTINCT CAST("col1" AS CHAR(1)),
CAST(to_char("col2",'00.0000') AS char(7))
FROM tableA
the col2 has data like 22.33 or 2.3 or 0.2345 or 2 but, four digits in dec and 2 digits in number.
It has to be written into a file with fixed length of 7 digits including decimal. Hence i wrote col2, '00.0000', but the number format'23.234' is written into col2 as 23.234 without any trailing zero.
Your format code of 00.0000 should include the fourth decimal place for 23.234; it's always worked for me. I'm using Oracle 11.
The problem I got when I tried doing CAST(TO_CHAR(23.234, '00.0000') AS CHAR(7)) was the error ORA-25137: Data value out of range. This happens because because the TO_CHAR returns a string of length 8:
SQL> SELECT '[' || TO_CHAR(23.234, '00.0000') || ']' FROM DUAL
'['||TO_CH
----------
[ 23.2340]
TO_CHAR leaves a space at the beginning in case the number is negative, in which case it will put a minus sign there. You can get rid of the leading space by using the FM modifier in the format string:
SQL> SELECT '[' || TO_CHAR(23.234, 'FM00.0000') || ']' FROM DUAL
'['||TO_CH
----------
[23.2340]
This is all a long way of saying "try this instead" - the only change is the FM in the TO_CHAR format string:
CREATE OR REPLACE VIEW viewA ("col1", "col2") AS
SELECT DISTINCT
CAST("col1" AS CHAR(1)),
CAST(to_char("col2",'FM00.0000') AS char(7))
FROM tableA
One final note: enclosing the column names with double quotes makes them case sensitive, and that often leads to trouble. I'd recommend losing the double quotes if you can.
You need to use the RPAD function that would add trailing zeros for you
CREATE OR REPLACE VIEW viewA ("col1", "col2") AS
SELECT DISTINCT CAST("col1" AS CHAR(1)),
RPAD(CAST(to_char("col2",'00.0000') AS char(7)),7,'0')
FROM tableA
But you might face a problem if your number did not have a decimal value, for example assuming the value is 12 you will end up with 1200000 but maybe this would give you an idea

Remove leading zeros

Given data in a column which look like this:
00001 00
00026 00
I need to use SQL to remove anything after the space and all leading zeros from the values so that the final output will be:
1
26
How can I best do this?
Btw I'm using DB2
This was tested on DB2 for Linux/Unix/Windows and z/OS.
You can use the LOCATE() function in DB2 to find the character position of the first space in a string, and then send that to SUBSTR() as the end location (minus one) to get only the first number of the string. Casting to INT will get rid of the leading zeros, but if you need it in string form, you can CAST again to CHAR.
SELECT CAST(SUBSTR(col, 1, LOCATE(' ', col) - 1) AS INT)
FROM tab
In DB2 (Express-C 9.7.5) you can use the SQL standard TRIM() function:
db2 => CREATE TABLE tbl (vc VARCHAR(64))
DB20000I The SQL command completed successfully.
db2 => INSERT INTO tbl (vc) VALUES ('00001 00'), ('00026 00')
DB20000I The SQL command completed successfully.
db2 => SELECT TRIM(TRIM('0' FROM vc)) AS trimmed FROM tbl
TRIMMED
----------------------------------------------------------------
1
26
2 record(s) selected.
The inner TRIM() removes leading and trailing zero characters, while the outer trim removes spaces.
This worked for me on the AS400 DB2.
The "L" stands for Leading.
You can also use "T" for Trailing.
I am assuming the field type is currently VARCHAR, do you need to store things other than INTs?
If the field type was INT, they would be removed automatically.
Alternatively, to select the values:
SELECT (CAST(CAST Col1 AS int) AS varchar) AS Col1
I found this thread for some reason and find it odd that no one actually answered the question. It seems that the goal is to return a left adjusted field:
SELECT
TRIM(L '0' FROM SUBSTR(trim(col) || ' ',1,LOCATE(' ',trim(col) || ' ') - 1))
FROM tab
One option is implicit casting: SELECT SUBSTR(column, 1, 5) + 0 AS column_as_number ...
That assumes that the structure is nnnnn nn, ie exactly 5 characters, a space and two more characters.
Explicit casting, ie SUBSTR(column,1,5)::INT is also a possibility, but exact syntax depends on the RDBMS in question.
Use the following to achieve this when the space location is variable, or even when it's fixed and you want to make a more robust query (in case it moves later):
SELECT CAST(SUBSTR(LTRIM('00123 45'), 1, CASE WHEN LOCATE(' ', LTRIM('00123 45')) <= 1 THEN LEN('00123 45') ELSE LOCATE(' ', LTRIM('00123 45')) - 1 END) AS BIGINT)
If you know the column will always contain a blank space after the start:
SELECT CAST(LOCATE(LTRIM('00123 45'), 1, LOCATE(' ', LTRIM('00123 45')) - 1) AS BIGINT)
both of these result in:
123
so your query would
SELECT CAST(SUBSTR(LTRIM(myCol1), 1, CASE WHEN LOCATE(' ', LTRIM(myCol1)) <= 1 THEN LEN(myCol1) ELSE LOCATE(' ', LTRIM(myCol1)) - 1 END) AS BIGINT)
FROM myTable1
This removes any content after the first space character (ignoring leading spaces), and then converts the remainder to a 64bit integer which will then remove all leading zeroes.
If you want to keep all the numbers and just remove the leading zeroes and any spaces you can use:
SELECT CAST(REPLACE('00123 45', ' ', '') AS BIGINT)
While my answer might seem quite verbose compared to simply SELECT CAST(SUBSTR(myCol1, 1, 5) AS BIGINT) FROM myTable1 but it allows for the space character to not always be there, situations where the myCol1 value is not of the form nnnnn nn if the string is nn nn then the convert to int will fail.
Remember to be careful if you use the TRIM function to remove the leading zeroes, and actually in all situations you will need to test your code with data like 00120 00 and see if it returns 12 instead of the correct value of 120.

Get all characters before space in MySQL

I would like to get all the characters in a field before a space
For example, if field1 is "chara ters"
I want it to return "chara"
What would this select statement look like?
SELECT LEFT(field1,LOCATE(' ',field1) - 1)
Note that if the string in question contains no spaces, this will return an empty string.
Below is another method that works and may seem a bit simpler to some. It uses the SUBSTRING_INDEX MySQL function. A 1 returns everything before the first space, and a -1 returns everything after the last space.
This returns 'chara':
SELECT SUBSTRING_INDEX( field1, ' ', 1 )
This returns 'ters':
SELECT SUBSTRING_INDEX( field1, ' ', -1 )
Details
A positive value will look for your specified character from the start of the string, and a negative value will start from the end of the string. The value of the number indicates the quantity of your specified character to look for before returning the remaining piece of the string. If the character you are searching for does not exist, the entire field value will be returned.
In this case, a -2 would return everything to the right of the second to last space, which doesn't exist in this example, so the entire field value will be returned.
You would need some string operations for that. Assuming every field has at least one space character:
SELECT SUBSTR(field1, 0, LOCATE(' ', field1)) FROM your_table;
Safe approach:
SELECT IF(
LOCATE(' ', field1),
SUBSTR(field1, 0, LOCATE(' ', field1)),
field1
) FROM your_table;
For a generalized approach that returns the nth value (one-based index) from a column containing delimited values:
select SUBSTRING_INDEX(SUBSTRING_INDEX(my_column,#delimiter,#index),#delimiter,-1) from my_table;
This will return the entire column contents if the delimiter does not exist, and the last field if the index value exceeds the number of fields.
For instance, if my_column contains 'foo bar baz' and you want the 2nd field:
select SUBSTRING_INDEX(SUBSTRING_INDEX(my_column,' ',2),' ',-1) from my_table;
will return bar, and if you specify the 4th field (which does not exist):
select SUBSTRING_INDEX(SUBSTRING_INDEX(my_column,' ',4),' ',-1) from my_table;
will return baz (the last field).