Sorting in T-SQL - sql-server-2005

I have some strings like
"999"
"555"
"7777"
"CC44"
"AAAA"
"BBBB"
How can I sort so that the output will be
"999"
"7777"
"555"
"AAAA"
"BBBB"
"CC44"
The rule is : Based on the string's numeric value in ascending order
I have included the script too
declare #tbl Table(
data VARCHAR(MAX)
)
INSERT INTO #tbl (data)
SELECT '999' UNION ALL
SELECT '555' UNION ALL
SELECT '7777' UNION ALL
SELECT 'CC44' UNION ALL
SELECT 'AAAA' UNION ALL
SELECT 'BBBB'

That isn't a natural sort order, so you might need to add another column to perform the sorting. If that isn't possible, you will need to split the data set, sort each half, and rejoin them.
SELECT data FROM tbl WHERE columnname > "0" AND columnname < "9999" ORDER BY columnname DESC
UNION ALL
SELECT data FROM tbl WHERE columnname < "9999"
ORDER BY columnname ASC

Not tested but:
select col where IsNumeric(col)=1
order by IsNumeric(col) asc, col

Related

Select only rows with each word beginning with capital letter being output

I am trying to output data from a SQL database for only values where each word begins with a capital letter. If I have the Products column with values of "Product One Apple" and "Product two banana", I would only want to output any values such as "Product One Apple". I am not wanting to update any data, just manipulate the data output. Is this possible without the use of a function, or will this require one?
If you are using SQL Server:-
Table Creation:
create table YourTable(id int identity(1,1),YourColumn varchar(100));
insert into YourTable(YourColumn)
select 'One Letter' Name union all
select 'another One' union all
select 'lower case' union all
select 'Upper case Sensitiive charecters'
Fetch Data:
with SPosition as
(select patindex('% %',YourColumn) SPosition, YourColumn from YourTable
union all
select SPosition+patindex('% %',substring(YourColumn, SPosition+1, len(YourColumn))) SPosition, YourColumn from SPosition
where patindex('% %',substring(YourColumn, SPosition+1, len(YourColumn)))>0
),SelectedWords as(
select substring(YourColumn,SPosition+1,1) StartingPosition,Case When substring(YourColumn,SPosition+1,1) Collate Latin1_General_CS_AI=upper(substring(YourColumn,SPosition+1,1))
then isnull(nullif(ltrim(rtrim(substring(YourColumn,SPosition+1,patindex('% %',substring(YourColumn, SPosition+1, len(YourColumn)))))),''),
substring(YourColumn,SPosition+1,len(YourColumn)))
else null end Words,
SPosition,YourColumn from SPosition
union all
select substring(YourColumn,1,1),Case When substring(YourColumn,1,1) Collate Latin1_General_CS_AI=upper(substring(YourColumn,1,1))
then isnull(nullif(ltrim(rtrim(substring(YourColumn,1,patindex('% %',substring(YourColumn, 1, len(YourColumn)))))),''),
substring(YourColumn,1,len(YourColumn)))
else null end,
1,YourColumn from YourTable
)
select YourColumn,String_Agg(Words,',') from SelectedWords where Words is not null
group by YourColumn
You can run this code by Click Here
yes you can do with following query
Select CONCAT(UPPER(SUBSTRING(colunm_name,1,1)),LOWER(SUBSTRING(column_name,2))) AS Name from table_name;
You can get the ASCII representation number of the first letter, and validate the range between 65 and 90, which are the position that upper letters have in the ASCII table (ex. "#" represents the 64th position):
select d.Name, LEFT(d.Name, 1),ASCII(LEFT(d.Name, 1))
from (
select 'One Letter' Name union all
select 'another One' union all
select 'lower case' union all
select 'Upper'
)d
where ASCII(LEFT(d.Name, 1)) between 65 and 90 --Here the validation
If you want to review the ASCII table (decimal position), check this link: ASCII Table

SQL - Reverse Part of Column

I want to reverse part of column. Ex;
SELECT Column FROM Table ORDER BY Column ASC
Output:
Column
------
Kaan001
Kaan002
Kaan003
Turan001
Turan002
If I use DESC instead of ASC;
Column
------
Turan002
Turan001
Kaan003
Kaan002
Kaan001
But I want this;
Column
------
Turan001
Turan002
Kaan001
Kaan002
Kaan003
Is it possible or not? Please Help me... Thank you..
You can use:
order by left(columnname, len(columnname) - 3) desc,
right(columnname, 3)
You are required to use DESC. It will return the result by the mentioned column in the descending order.
SELECT ColumnName FROM TableName ORDER BY ColumnName DESC
If you are not explicitly mentioned the Column's ORDER BY it will consider as ASC (ascending order) by default.
Demo on db<>fiddle
As per your edited question, the following query will work using PATINDEX
SELECT ColumnName
FROM TableName
ORDER BY LEFT(ColumnName, PATINDEX('%[0-9]%', ColumnName) - 1) DESC,
RIGHT(ColumnName, LEN(ColumnName) - PATINDEX('%[0-9]%', ColumnName) + 1) ASC
Updated db<>fiddle demo
You can try the below query.
create table #temp (
id int identity(1,1),
testCol Varchar(20)
)
insert into #temp values ('Turan002'),('Turan001'),('Kaan003'),('Kaan002'),('Kaan001')
SELECT
* from
#temp order by RTRIM(SUBSTRING( testCol , 1 , CHARINDEX( '0' , testCol) - 1)) desc,
RTRIM(SUBSTRING( testCol , CHARINDEX( '0' , testCol ), LEN( testCol) - (CHARINDEX( '0' , testCol) - 1))) asc
drop table #temp
You can find the demo Here.
From my understanding,
select * from (
values
('Kaan001')
,('Kaan002')
,('Kaan003')
,('Turan001')
,('Turan002')
) d (val)
order by left (val, PATINDEX ('%[0-9]%', val) - 1) desc
, right (val, PATINDEX ('%[0-9]%', val)) -- Here, Patindex returns the first appearance of integer.

SQL Server converting string to numeric and sorting

I am attempting to sort a column of strings, which contains one alphanumeric character and a numbers. If I run this:
select
column_name
from
table_name
where
item_type = 'ABC'
and item_sub_type = 'DEF'
order by
cast(replace([column_name], 'A', '') as Numeric(10, 0)) desc
I get the correct sorted output:
A218
A217
A216
but if I try to grab the top row
select top 1
column_name
from
table_name
where
item_type = 'ABC'
and item_sub_type = 'DEF'
order by
cast(replace([column_name], 'A', '') as numeric(10, 0)) desc
it fails with the following error:
Error converting data type varchar to numeric
Any ideas on how I can select the top row?
Thanks!
I think this is the problem with your data - not all are match your pattern.
You can check what is not valid using:
select column_name from table_name where ISNUMERIC(replace([column_name],'A','')) = 0
I think this is the optimizer not executing your query how you would hope. What I mean is SQL is a declarative language--your query merely states what you are trying to accomplish, not how you are trying to accomplish it (in most cases). Thus, the optimizer determines the best way and in cases as yours, does things in certain order that causes errors. Try and force your logic with a CTE.
with cte as(
select column_name, [item_value]
from table_name
where item_type='ABC' and item_sub_type='DEF')
select top 1 column_name
from cte
ORDER BY CAST(replace([item_value],'A','') AS Numeric(10,0)) desc
SQL Server 2012/2016
select top 1 column_name
from table_name
where item_type='ABC' and item_sub_type='DEF'
order by TRY_CONVERT(Numeric(10,0),replace([column_name],'A','')) desc
Order by dropping the prefix and casting to int, provided that the prefix is the only non-numeric the rest should be pure numbers.
select
column_name
from
table_name
where
item_type = 'ABC'
and item_sub_type = 'DEF'
order by
cast(replace([column_name], 'A', '') as Int) desc
the script above should just work, i reckon there is something wrong with your data could multiple values...
see example below
declare #mytable table
(
code varchar(10)
)
insert into #mytable
values
('A323'),
('A223'),
('A123'),
('A553'),
('A923'),
('A23'),
('A235')
select
code
from
#mytable
order by
cast(replace(code, 'A', '') as Int) desc
code
----------
A923
A553
A323
A235
A223
A123
A23

Dynamic Comma Seperated string into different column

May someone please help me for this strange scenario. i have a data as given below.
DECLARE #TABLE TABLE
(
ID INT,
PHONE001 VARCHAR(500)
)
INSERT TEST
SELECT 1,'01323840261,01323844711' UNION ALL
SELECT 2,'' UNION ALL
SELECT 3,',01476862000' UNION ALL
SELECT 4,'01233625418,1223822583,125985' UNION ALL
SELECT 5,'2089840022,9.99021E+13'
and i am trying to put in seperate column for each comma value. the max number of column depends on the largest comma seperated string.
Expected Output
1|01323840261|01323844711|''
2|''|''|''
3|01476862000|''|''|
4|01233625418|1223822583|125985|
5|2089840022|9.99021E+13|''|
try
select id,T.c.value('t[1]','varchar(50)') as col1,
T.c.value('t[2]','varchar(50)') as col2 ,
T.c.value('t[3]','varchar(50)') as col3 from
(select id,cast ('<t>'+ replace(PHONE001,',','</t><t>') +'</t>'
as xml) x
from #TABLE) a cross apply x.nodes('.') t(c)

SQL to generate next sequence in an alphanumeric id

I gained some help from this question, but still need some further assistance.
I need to be able to generate the next available 2-digit alphanumeric code. I cannot change the table definition, before you ask. I am working in T-SQL.
So, for example, let's say I have the sequence
00, 01, 02,..., 09, 0A, 0B, 0C,..., 0Y, 0Z, 10, 11,...1Y, 1Z, 20, 21,..., 9Y, 9Z, I would like for the next id to be A0,
then A1, A2, ..., A9, AA, AB, AC, ..., AZ, I would like for the next id to be B0, then B1, etc.
So, in short, I would like to go from 00 all the way to ZZ and each time look for the MAX in that field and assign a new code 1 greater than the max. I would understand that A > 9, and the first column greater than the second, so A0 > 99 and AA > A9.
I wish I could just assign a numeric id to all of this, but the table definition is more critical at this point and so I'm not allowed to change it, so I am trying to maximize the available ids I'll have in such a limited space.
Thank you for your help.
Have a look at this. This is a really nasty problem for ID's. You've effectively limited yourself a low number of permutations of the key with 2 characters. Also you have a problem that you'll need to deal with if ZZ is used and this algorithm runs again. I have expanded these into as logical steps as possible for demonstration, but feel free to condense as needed.
DECLARE #ExistingTable TABLE (ID CHAR(2))
INSERT INTO #ExistingTable (ID) VALUES ('5A'),('5B')
DECLARE #NewID CHAR(2)
;WITH
Ranks AS (
SELECT '0' AS [Character] UNION SELECT '1' AS [Character] UNION SELECT '2' UNION SELECT '3' UNION SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT 'A' UNION SELECT 'B'UNION
SELECT 'C' UNION SELECT 'D' UNION SELECT 'E' UNION SELECT 'F' UNION SELECT 'G' UNION SELECT 'H' UNION
SELECT 'I' UNION SELECT 'J' UNION SELECT 'K' UNION SELECT 'L' UNION SELECT 'M' UNION SELECT 'N' UNION
SELECT 'O' UNION SELECT 'P' UNION SELECT 'Q' UNION SELECT 'R' UNION SELECT 'S' UNION SELECT 'T' UNION
SELECT 'U' UNION SELECT 'V' UNION SELECT 'W' UNION SELECT 'X' UNION SELECT 'Y' UNION SELECT 'Z'
), Permutations AS (
SELECT SecondChar.[Character] + FirstChar.[Character] AS PermuteID
FROM Ranks AS FirstChar
CROSS JOIN Ranks AS SecondChar
), PermutationsKeyed AS (
SELECT ROW_NUMBER() OVER (ORDER BY PermuteID ASC) AS PrimaryKeyHolder,
PermuteID
FROM Permutations
), MaxPK AS (
SELECT MAX(Perm.PrimaryKeyHolder) + 1 AS MaxPK
FROM #ExistingTable AS E
INNER JOIN PermutationsKeyed AS Perm ON (E.ID = Perm.PermuteID)
)
SELECT #NewID = Perm.PermuteID
FROM PermutationsKeyed AS Perm
INNER JOIN MaxPK AS M ON (Perm.PrimaryKeyHolder = M.MaxPK)
SELECT #NewID
I'm not sure how you wanted to go about returning the next value but I think this a simple and efficient ways to get all your values. Let me know if you need anything else.
DECLARE #values TABLE (val CHAR(1));
DECLARE #int INT = 48,
#letters INT = 65;
IF OBJECT_ID('dbo.tbl_keys') IS NOT NULL
DROP TABLE dbo.tbl_keys;
--This will hold the values so you can always reference them
CREATE TABLE dbo.tbl_Keys
(
--Primary key will create a clustered index on rank_id by default
rank_id INT PRIMARY KEY,
ID_Code CHAR(2)
);
--Another index on ID_Code
CREATE NONCLUSTERED INDEX idx_ID_Code ON tbl_keys(ID_Code);
--This is how I get all your individual values
WHILE (SELECT COUNT(*) FROM #values) < 36
BEGIN
IF(#int <= 57)
INSERT INTO #values VALUES(CHAR(#int));
INSERT INTO #values
VALUES (CHAR(#letters))
SET #int = #int + 1;
SET #letters = #letters + 1;
END
--Insert all possible combinations and rank them
INSERT INTO tbl_Keys
--ASCII is your best friend. It returns the ASCII code(numeric value) for characters
SELECT ROW_NUMBER() OVER (ORDER BY ASCII(A.val),ASCII(B.val)) AS rank_id,
A.val + B.val ID
FROM #values A
CROSS JOIN #values B;
I provide two different ways of getting the next ID_code(Read comments):
--Here's some dummy data
WITH CTE_DummyTable
AS
(
SELECT '00' ID_Code
UNION ALL
SELECT '01'
UNION ALL
SELECT '02'
)
----Here's how to get the next value with the assumption there are no gaps in your data
--SELECT MIN(ID_Code) next_id_code
--FROM tbl_Keys
--WHERE ID_code > (SELECT MAX(id_code) FROM CTE_DummyTable)
--This one doesn't assume the gaps and returns the lowest available ID_code
SELECT MIN(ID_Code) next_id_code
FROM tbl_Keys
WHERE ID_code NOT IN (SELECT DISTINCT id_code FROM CTE_DummyTable)
Note: If you were ever to want to convert your alphanumeric values really easily for whatever reason without changing the rank try this.
SELECT rank_id,
ID_code,
CAST(CONCAT(ASCII(LEFT(id_code,1)),ASCII(RIGHT(id_code,1))) AS INT) AS numeric_id_code
FROM tbl_Keys