I have a column with data like this:
COMPRESSIN 1(PB4),
COMPRESSIN 12(PB4),
COMPRESSIN 3(PB4).
I want to order the column by the COMPRESSION. So 1, 3, and 12 respectively as shown below:
COMPRESSION 1(PB4),
COMPRESSION 3(PB4),
COMPRESSION 12(PB4).
You need to order by a substring.
...
order by
substring(yourColumn,12,99)
This basically sorts on everything after 'COMPRESSION ' It's important to know that this is still sorting based on varchar order, which is using unicode decimal values. Thus, b comes before A due to it's case sensitivity, etc...
If your columns all end with the (XXX) pattern, you can use this to circumvent this.
order by
left(substring(yourColumn,12,99),len(substring(yourColumn,12,99)) - 5)
Another way you can do this is to remove the non-numeric portion while ordering:
ORDER BY CAST(
REPLACE(
REPLACE(YourColumn, 'COMPRESSION ','')
, '(PB4)','')
AS int) ASC
Here is a potential solution or at least one that can help put you in the right direction. I recommend you consider the clarity of your question and add more detail.
SELECT
ColumnName
FROM
TableName
ORDER BY
CAST(SUBSTRING(ColumnName, CHARINDEX(' ', ColumnName) + 1, CHARINDEX('(', ColumnName) - CHARINDEX(' ', ColumnName) - 1) AS int)
This works by using CHARINDEX to find the space after compression as a starting position (+1 to begin after the space) and the open parenthesis as the ending position to isolate the numeric value for sorting. You also need to convert this value to some type of numeric value like an integer.
Related
I have a view that is defined like so:
CREATE VIEW dbo.v_ListingTestView
WITH SCHEMABINDING
AS
SELECT
[ListingID],
[BusinessName],
[Description],
[ProductDescription],
[Website],
[ListingTypeID],
ISNULL([BusinessName], '') + ' ' + ISNULL([Description], '') + ' ' + ISNULL([ProductDescription], '') + ' ' AS [ComputedText]
FROM dbo.Listings;
I use this view when a user searches for a record in the database. The keyword the user provides when searching is compared to the computed column. The columns that are included in the computed column are all NVARCHAR columns. I would like to create an index on this column to help speed up searching.
I was following a tutorial to add an index to the computed column, but I ran into an issue where my computed column was non-deterministic and could not complete the tutorial. If anyone has suggestions on how to accomplish this I would appreciate it. Or if I should go about this a different way.
What length are your columns? ISNULL() is a deterministic function and shouldn't cause any issues.
I'm guessing that's length of your columns that causes it. As you might know, index cannot be longer than 900 symbols. Since you're storing them as NVARCHAR, it takes double space as a varchar and needs additional two bytes - this means your index can store up to 448 symbols.
Variable-length Unicode string data. n defines the string length and
can be a value from 1 through 4,000. max indicates that the maximum
storage size is 2^31-1 bytes (2 GB). The storage size, in bytes, is
two times the actual length of data entered + 2 bytes. The ISO
synonyms for nvarchar are national char varying and national character
varying.
So please try to cast your column at specific length, perhaps 400?
CREATE VIEW dbo.v_ListingTestView
WITH SCHEMABINDING
AS
SELECT [ListingID]
, [BusinessName]
, [Description]
, [ProductDescription]
, [Website]
, [ListingTypeID]
, CAST(ISNULL([BusinessName], '') + ' ' + ISNULL([Description], '') + ' ' + ISNULL([ProductDescription], '') AS NVARCHAR(400)) AS [ComputedText]
FROM dbo.Listings;
On top of that, why you'd be creating a view on top of that? Perhaps it would make more sense to alter your table accordingly and only then add index on it:
ALTER TABLE dbo.Listings
ADD [ComputedText] AS CAST(ISNULL([BusinessName], '') + ' ' + ISNULL([Description], '') + ' ' + ISNULL([ProductDescription], '') AS NVARCHAR(400));
Now knowing that your NVARCHARS are stored as MAX, perhaps it would be a better idea to start using Full Text Search? This question might be worth looking at then: How do you implement a fulltext search over multiple columns in sql server?
I know to do parts of it but not all of it, lets say my table name is REV and column name is DESCR and it has a value like
R&B , Semiprivate 2 Beds , Medical/Surgical/GYN
i use
SELECT DESCR, LEFT(DESCR, Charindex(',', DESCR)), SUBSTRING(DESCR, CHARINDEX(',', DESCR) + 1, LEN(DESCR)) from REV
i get 'R&B ,' in one column and 'Semiprivate 2 Beds , Medical/Surgical/GYN' in another column in the above select statement but i dont know how to selesct the strings from teh second comma onwards
what i like to return is 'R&B' in one column without the comma and 'Semiprivate 2 Beds' in another column and 'Medical/Surgical/GYN' so on
basically select test between commas and when there is no comma it should be blank
This should work:
SELECT
LEFT(DESCR, CHARINDEX(',', DESCR)-1),
SUBSTRING(DESCR, CHARINDEX(',', DESCR)+1, CHARINDEX(',', DESCR, CHARINDEX(',', DESCR)+1) - CHARINDEX(',', DESCR) -1 ),
RIGHT(DESCR, CHARINDEX(',', REVERSE(DESCR))-1)
FROM REV
This should work:
SELECT
LEFT(DESCR, CHARINDEX(',', DESCR)-1),
SUBSTRING(DESCR, CHARINDEX(',', DESCR)+1, LEN(DESCR)-CHARINDEX(',', DESCR)-CHARINDEX(',',REVERSE(DESCR ))),
RIGHT(DESCR, CHARINDEX(',', REVERSE(DESCR))-1)
FROM REV
Sample SQL Fiddle
This will split the string, but leave blank at the beginning and end of the strings, you can use LTRIMand RTRIMto trim away the blanks.
There might be better ways to do this though; see the article Split strings the right way – or the next best way by Aaron Bertrand at (that Andrew mentioned in a comment).
I have an MSSQL database field that looks like the examples below:
u129 james
u300 chris
u300a jim
u202 jane
u5 brian
u5z brian2
Is there a way to select the first set of characters? Basically select all the characters up until the first line space?
I tried messing around with LEFT, RIGHT, LEN, but couldn't figure out a way to do it with variable string lengths like in my example.
Thanks!
You can use a combiation of LEFT and CHARINDEX to find the index of the first space, and then grab everything to the left of that.
SELECT LEFT(YourColumn, charindex(' ', YourColumn) - 1)
And in case any of your columns don't have a space in them:
SELECT LEFT(YourColumn, CASE WHEN charindex(' ', YourColumn) = 0 THEN
LEN(YourColumn) ELSE charindex(' ', YourColumn) - 1 END)
select left(col, charindex(' ', col) - 1)
If the first column is always the same size (including the spaces), then you can just take those characters (via LEFT) and clean up the spaces (with RTRIM):
SELECT RTRIM(LEFT(YourColumn, YourColumnSize))
Alternatively, you can extract the second (or third, etc.) column (using SUBSTRING):
SELECT RTRIM(SUBSTRING(YourColumn, PreviousColumnSizes, YourColumnSize))
One benefit of this approach (especially if YourColumn is the result of a computation) is that YourColumn is only specified once.
An alternative if you sometimes do not have spaces do not want to use the CASE statement
select REVERSE(RIGHT(REVERSE(YourColumn), LEN(YourColumn) - CHARINDEX(' ', REVERSE(YourColumn))))
This works in SQL Server, and according to my searching MySQL has the same functions
If space is missing, you can add one
SELECT LEFT('YourTextOrColumn',
charindex(' ',
'YourTextOrColumn' + ' ') - 1 )
I'm looking for an elegant way to convert a field of type varchar, with variable data in it, to a data type which can be used for mathematical operations sample data from the field
(excluding quotes)
''
'abc'
'23'
'23.2'
The method should work for all, and for the first & second values should return 0, and not throw an SQL Server error..
Try this:
SELECT CASE WHEN IsNumeric(YourColumn) = 0 THEN
0
ELSE
CAST(YourColumn AS decimal(18, 2))
END
You have to adjust the destination data type, I have chosen decimal(18, 2) for demonstration.
I know this is a long-dead thread, but I recently stumbled upon it from a Google search and had a thought. It is less elegant than a CASE statement, but it is an alternative.
SELECT
COALESCE(CAST(NULLIF(ISNUMERIC(LEFT(MyColumn, PATINDEX('% %', MyColumn + ' ') - 1)), 1) AS MONEY), LEFT(MyColumn, PATINDEX('% %', MyColumn + ' ') - 1))
FROM
myTable
or you could do:
Select COALESCE(CAST(NULLIF(ISNUMERIC(MyColumn), 1) AS MONEY), MyColumn)
FROM
myTable
The top version would see "2 5" as just 2, the bottom one would see it as a text field.
SELECT CASE IsNumeric(mycol) WHEN 1 THEN CAST(mycol AS FLOAT) ELSE 0 END
FROM mytable
If you'd like to convert it, you should use UPDATE instead of SELECT
UPDATE Table
SET Col1 = CAST(Col1 As Decimal(18,2))
COALESCE is a great option for this: Find more information here. It evaluates the arguments in order and returns the current value of the first expression that initially does not evaluate to NULL.
ISNUMERIC returns 0 or 1 depending on if the value being evaluated could be considered one of the SQL 'number' or 'numeric' types. e.g. int, bigint, money..
NULLIF essentially finds the value you specify and if it matches it replaces it with a NULL value.
CAST Simply changes a data type to another in this example to MONEY
As you can see, if you break the below down using this information its quite an elegant solution I think?
COALESCE(CAST(NULLIF(ISNUMERIC(COL1), 1) AS MONEY), COL1)
If I have the following nvarchar variable - BTA200, how can I extract just the BTA from it?
Also, if I have varying lengths such as BTA50, BTA030, how can I extract just the numeric part?
I would recommend a combination of PatIndex and Left. Carefully constructed, you can write a query that always works, no matter what your data looks like.
Ex:
Declare #Temp Table(Data VarChar(20))
Insert Into #Temp Values('BTA200')
Insert Into #Temp Values('BTA50')
Insert Into #Temp Values('BTA030')
Insert Into #Temp Values('BTA')
Insert Into #Temp Values('123')
Insert Into #Temp Values('X999')
Select Data, Left(Data, PatIndex('%[0-9]%', Data + '1') - 1)
From #Temp
PatIndex will look for the first character that falls in the range of 0-9, and return it's character position, which you can use with the LEFT function to extract the correct data. Note that PatIndex is actually using Data + '1'. This protects us from data where there are no numbers found. If there are no numbers, PatIndex would return 0. In this case, the LEFT function would error because we are using Left(Data, PatIndex - 1). When PatIndex returns 0, we would end up with Left(Data, -1) which returns an error.
There are still ways this can fail. For a full explanation, I encourage you to read:
Extracting numbers with SQL Server
That article shows how to get numbers out of a string. In your case, you want to get alpha characters instead. However, the process is similar enough that you can probably learn something useful out of it.
substring(field, 1,3) will work on your examples.
select substring(field, 1,3) from table
Also, if the alphabetic part is of variable length, you can do this to extract the alphabetic part:
select substring(field, 1, PATINDEX('%[1234567890]%', field) -1)
from table
where PATINDEX('%[1234567890]%', field) > 0
LEFT ('BTA200', 3) will work for the examples you have given, as in :
SELECT LEFT(MyField, 3)
FROM MyTable
To extract the numeric part, you can use this code
SELECT RIGHT(MyField, LEN(MyField) - 3)
FROM MyTable
WHERE MyField LIKE 'BTA%'
--Only have this test if your data does not always start with BTA.
declare #data as varchar(50)
set #data='ciao335'
--get text
Select Left(#Data, PatIndex('%[0-9]%', #Data + '1') - 1) ---->>ciao
--get numeric
Select right(#Data, len(#data) - (PatIndex('%[0-9]%', #Data )-1) ) ---->>335