June 21, 2007 at 2:55 pm
All,
I found a few posts that I thought applied to what I am trying to do. So, I here is the code and sample data I working with:
DECLARE @TestData TABLE (StringValue VARCHAR(20))
INSERT INTO @TestData
SELECT '10' UNION ALL
SELECT '22' UNION ALL
SELECT '1A' UNION ALL
SELECT '1' UNION ALL
SELECT 'S1' UNION ALL
SELECT '3B' UNION ALL
SELECT '4' UNION ALL
SELECT '7'
SELECT StringValue
FROM @TestData
ORDER BY CASE WHEN ISNUMERIC(StringValue) = 1 THEN CAST(StringValue AS INT) END ASC,
CASE WHEN ISNUMERIC(StringValue) = 0 THEN StringValue END ASC
The sort order i get back is:
1A
3B
S1
1
4
7
10
22
What I want is
1
1A
3B
4
7
10
22
S1
Basically, I want the numeric characters sorted first followed by the alpha characters.
June 21, 2007 at 3:02 pm
Normalize your table.
_____________
Code for TallyGenerator
June 22, 2007 at 3:55 pm
How would that help?
Try this
SELECT
StringValue
FROM (
SELECT StringValue,
CASE
WHEN StringValue LIKE '[0-9]%' THEN 0
ELSE 1
END AS Alpha,
CASE
WHEN PATINDEX('%[^0-9]%', StringValue) = 0 THEN StringValue
ELSE LEFT(StringValue, PATINDEX('%[^0-9]%', StringValue) - 1)
END AS Value
FROM @TestData
) AS d
ORDER BY Alpha,
LEN(Value),
Value,
StringValue
N 56°04'39.16"
E 12°55'05.25"
June 22, 2007 at 4:11 pm
Then what did you do?
You split original column into 2 (normalized the data) and built derived table with normalized data on fly.
No indexes, no statistics.
Worst possible approach.
Populate @TestData with 100k rows and see how long will it take to do this ordering.
_____________
Code for TallyGenerator
June 22, 2007 at 4:15 pm
Please demonstrate how you would solve this then!
You just can't tell people to "Normalize your table" when you have absolutely no idea what the data represents.
I would have guessed that they are part of street addresses, but 'S1' is present.
N 56°04'39.16"
E 12°55'05.25"
June 22, 2007 at 4:21 pm
By the way it requested to be ordered I can conclude it's 2 concatenated values.
Saving concatenated strings in tables is an error which will cause (already causes) problems in retrieving data.
_____________
Code for TallyGenerator
June 22, 2007 at 4:25 pm
How can you tell?
Are you sure they are not serial numbers? Encrypted values?
We do not simply know and have not enough information to do that assumption.
You are similar to President Putin, who not long ago said in a television interview "Russia is the only true democratic country in the world".
You are always convinced that you are never wrong.
N 56°04'39.16"
E 12°55'05.25"
June 22, 2007 at 7:23 pm
I can tell.
It's ordered to sort by some kind of group (integer value at the beginning) and then by item (second part).
And you cannot explain why to sort serial numbers like that.
So, it's not serial numbers.
Any ideas not matching my?
P.S. I see you're very educated person. You know the name "Putin".
_____________
Code for TallyGenerator
June 22, 2007 at 7:30 pm
> You are always convinced that you are never wrong.
Are you sure you are right?
_____________
Code for TallyGenerator
June 22, 2007 at 8:36 pm
I always wanted to know how fast that method ran
--================================================================================================= -- Prepare a test table --=================================================================================================
--===== If the test table exists, drop IF OBJECT_ID('TempDB.dbo.#TestData') IS NOT NULL DROP TABLE #TestData GO --===== Create and populate the test table with 100000 rows SELECT TOP 100000 RowNum = IDENTITY(INT,1,1), StringValue = CAST(NULL AS VARCHAR(10)) INTO #TestData FROM Master.dbo.SysColumns sc1, Master.dbo.SysColumns sc2 --Lack of join criteria makes this a CROSS-JOIN
--===== Add a primary key ALTER TABLE dbo.#TestData ADD PRIMARY KEY CLUSTERED (RowNum)
--===== Populate the table with a bunch of random data in the forms of N, A, NA, and AN UPDATE dbo.#TestData SET StringValue = CASE WHEN RowNum % 10 = 0 THEN CHAR(STR(RAND(CAST(NEWID() AS VARBINARY))*9+48)) --Digit WHEN RowNum % 5 = 0 THEN CHAR(STR(RAND(CAST(NEWID() AS VARBINARY))*25+65)) --Letter WHEN RowNum % 10 < 5 THEN CHAR(STR(RAND(CAST(NEWID() AS VARBINARY))*9+48)) --Digit + CHAR(STR(RAND(CAST(NEWID() AS VARBINARY))*25+65)) --Letter ELSE CHAR(STR(RAND(CAST(NEWID() AS VARBINARY))*25+65)) --Letter + CHAR(STR(RAND(CAST(NEWID() AS VARBINARY))*9+48)) --Digit END
--===== Take a look at the test data just because SELECT * FROM #TestData
--================================================================================================= -- Test the given solution for duration --================================================================================================= --===== Declare a timer variable and start the timer DECLARE @StartTime DATETIME SET @StartTime = GETDATE()
--===== Run the example code that was posted SELECT StringValue FROM ( SELECT StringValue, CASE WHEN StringValue LIKE '[0-9]%' THEN 0 ELSE 1 END AS Alpha, CASE WHEN PATINDEX('%[^0-9]%', StringValue) = 0 THEN StringValue ELSE LEFT(StringValue, PATINDEX('%[^0-9]%', StringValue) - 1) END AS Value FROM #TestData ) AS d ORDER BY Alpha, LEN(Value), Value, StringValue
--===== Test complete... display the duration PRINT CONVERT(CHAR(12),GETDATE()-@StartTime,114) + ' Duration (hh:mm:ss:mil)'
--Jeff Moden
Change is inevitable... Change for the better is not.
June 22, 2007 at 8:38 pm
Bill,
Thanks for posting code that actually creates some data... usually saves a lot of time for respondents and we appreciated it a LOT!
--Jeff Moden
Change is inevitable... Change for the better is not.
June 23, 2007 at 12:12 am
Is it good or bad result?
Let's check:
SELECT StringValue,
CASE WHEN StringValue LIKE '[0-9]%' THEN 0 ELSE 1 END AS Alpha,
CONVERT(int, CASE
WHEN PATINDEX('%[^0-9]%', StringValue) = 0 THEN StringValue
ELSE LEFT(StringValue, PATINDEX('%[^0-9]%', StringValue) - 1)
END) AS Value
INTO #TestData2
FROM #TestData
DECLARE @StartTime DATETIME
SET @StartTime = GETDATE()
SELECT StringValue
FROM #TestData2
ORDER BY Alpha,
Value,
StringValue
PRINT CONVERT(CHAR(12),GETDATE()-@StartTime,114) + ' Duration (hh:mm:ss:mil)'
-----------------------
Well, 2.5 times faster on my computer.
What about yours?
_____________
Code for TallyGenerator
June 23, 2007 at 3:23 am
No, I am not.
I am just responding to a need that where posted here. I can't tell why he wants to sort the numbers the way he wanted. Maybe it is a business rule? Maybe it is easier to read and manually search from a printed list?
N 56°04'39.16"
E 12°55'05.25"
June 23, 2007 at 3:25 am
Why didn't you time your complete code posted 6/23/2007 12:12:00 AM?
You only timed the last select, not the "normalization part". Why?
And I can't see somewhere that you actually had made a workable solution of your own.
You are just riding on my original suggestion!
N 56°04'39.16"
E 12°55'05.25"
June 23, 2007 at 3:29 am
I agree with Jeff. Excellent work Bill with both creating a sample set, a clear definition of what you want and also (thumbs up) a complete resultset how you wanted the final result to be!
Kudos to you!
N 56°04'39.16"
E 12°55'05.25"
Viewing 15 posts - 1 through 15 (of 39 total)
You must be logged in to reply to this topic. Login to reply