I have a column in a table that is populated with a string
level 1, level 2, level 3 ... level 12.
I wish to order by this column but not alphabetically as this orders the column
1 10 11 12 2 3 4 5 6 7 8 9
How can I order this column to be in correct numerical order despite it being a string type?
I imagine I have to extract only the numerical component of the string and cast it to an int but I don't know how to do this in SQL Server.
Thanks
Try this:
Select *
From YourTable
Order by CAST( SUBSTRING(YourColumn, 6,LEN(YourColumn)) AS Int)
Try this:
SELECT *
FROM TableName
ORDER BY CAST(REPLACE(ColumnName, 'level', '') AS INT)
Try something like this:
SELECT col
FROM
(values('level 1'),('level 2'),('level 3'),
('level 5'),('level 8'),('level 10'),('level 12'))
x(col)
ORDER BY stuff(col, 1,6, '') + 0
The stuff will remove the first 6 characters, the +0 will cast the rest of the col as integer(which can also be done with cast or convert)
Related
I have a table with strings (ItemCode) like:
99XXX123456-789
12ABC221122-987BA1
They are always of a length of 11 characters (upto the - of which they always contain only one), after the - length is variable. I would like to get the part after the first 5 characters upto the - , like this.
123456
221122
I tried with substring and patindex:
SELECT SUBSTRING( ItemCode, 6, PATINDEX('%[-]%', ItemCode) - 6 ),
PATINDEX('%[-]%', ItemCode),
ItemCode
FROM TableName
WHERE LEFT(ItemCode, 5) = '99XXX'
Patindex itself returns the correct value (12) but with PATINDEX('%[-]%', ItemCode) - 6 /sql should understand this as 12 - 6 = 6 / SQL Server 2012 gives an error. I could use 6 as a fix value in the patindex for the length, of course but I want to understand the reason for the error.
But when I am using the same query I am not getting the error:
create table #temp
(
num varchar(50)
)
--insert into #temp values ('99XXX123456-789')
--insert into #temp values ('12ABC221122-987BA1')
SELECT SUBSTRING( num, 6, PATINDEX('%[-]%', num) - 6 ),
PATINDEX('%[-]%', num),
num
FROM #temp WHERE LEFT(num, 5) = '99XXX'
I want to update one table using another table on field "Id" such that it wont create duplicates
let say my first table is Table1 and second table is Table2 . I would like to update the row in Table1 from Table2 when the Id is matching
I am aware of using UNION function but this applies to entire columns where I only need to consider a single column. https://docs.snowflake.com/en/sql-reference/operators-query.html#union-all
Example of my Tables
Table1
Id name number value
1 a 8 100
2 b 8 100
3 c 8 100
4 d 8 100
Table2
Id name number value
3 c 8 99
4 d 6 100
5 e 7 100
Expected output
Id name number value
1 a 8 100
2 b 8 100
3 c 8 99
4 d 6 100
5 e 7 100
Please note that in the output table row with Id 3,4 has be updated and new Id 5 is inserted.
PS: It would be better if someone could provide me the select statement to get the output table.
The constuct you are searching for is called MERGE:
CREATE OR REPLACE TABLE trg(Id INT, name VARCHAR, number INT, value INT)
AS SELECT 1 ,'a', 8, 100
UNION SELECT 2 ,'b', 8, 100
UNION SELECT 3 ,'c', 8, 100
UNION SELECT 4 ,'d', 8, 100;
CREATE OR REPLACE TABLE src(Id INT, name VARCHAR, number INT, value INT)
AS SELECT 3 ,'c', 8, 99
UNION SELECT 4 ,'d', 6, 100
UNION SELECT 5 ,'e', 7, 100;
Query:
MERGE INTO trg
USING src
ON trg.Id = src.Id
WHEN MATCHED THEN UPDATE SET name = src.name,
number = src.number,
value = src.value
WHEN NOT MATCHED THEN INSERT (ID, name, number, value)
VALUES (src.Id, src.name, src.number, src.value);
SELECT * FROM trg;
Output:
EDIT:
PS: It would be better if someone could provide me the select statement to get the output table.
UNION ALL combined with QUALIFY could be used:
WITH cte AS (
SELECT *, 1 AS priority FROM trg
UNION ALL
SELECT *, 0 AS priority FROM src
)
SELECT Id, Name, Number, Value
FROM cte
QUALIFY ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Priority) = 1
ORDER BY Id;
I find this behaviour very strange and counterintuitive. (Even for SQL).
set ansi_nulls off
go
;with sampledata(Value, CanBeNull) as
(
select 1, 1
union
select 2, 2
union
select 3, null
union
select 4, null
union
select 5, null
union
select 6, null
)
select ROW_NUMBER() over(partition by CanBeNull order by value) 'RowNumber',* from sampledata
Which returns
1 3 NULL
2 4 NULL
3 5 NULL
4 6 NULL
1 1 1
1 2 2
Which means that all of the nulls are being treated as part of the same group for the purpose of calculating the row number. It doesn't matter whether the SET ANSI_NULLLS is on or off.
But since by definition the null is totally unknown then how can the nulls be grouped together like this? It is saying that for the purposes of placing things in a rank order that apples and oranges and the square root of minus 1 and quantum black holes or whatever can be meaningfully ordered. A little experimentation suggests that the first column is being used to generate the rank order as
select 1, '1'
union
select 2, '2'
union
select 5, null
union
select 6, null
union
select 3, null
union
select 4, null
generates the same values. This has significant implications which have caused problems in legacy code I am dealing with. Is this the expected behaviour and is there any way of mitigating it other than replacing the null in the select query with a unique value?
The results I would have expected would have been
1 3 NULL
1 4 NULL
1 5 NULL
1 6 NULL
1 1 1
1 2 2
Using Dense_Rank() makes no difference.
Yo.
So the deal is that when T-SQL is dealing with NULLs in predicates, it uses ternary logic (TRUE, FALSE or UNKNOWN) and displays the behavior that you have stated that you expect from your query. However, when it comes to grouping values, T-SQL treats NULLs as one group. So your query will group the NULLs together and start numbering the rows within that window.
For the results that you say you would like to see, this query should work...
WITH sampledata (Value, CanBeNull)
AS
(
SELECT 1, 1
UNION
SELECT 2, 2
UNION
SELECT 3, NULL
UNION
SELECT 4, NULL
UNION
SELECT 5, NULL
UNION
SELECT 6, NULL
)
SELECT
DENSE_RANK() OVER (PARTITION BY CanBeNull ORDER BY CASE WHEN CanBeNull IS NOT NULL THEN value END ASC) as RowNumber
,Value
,CanBeNull
FROM sampledata
Currently I'm working on a stored procedure to update the sort order of a table. The idea is to make sure that the correct rows are swapped.
INPUT: ToMoveID INT, Up BIT (1 up, 0 down)
SERVER: MSSQL 2012
example to use:
ID SortOrder UseForSwap
1 1 Yes
2 NULL No
3 2 Yes
4 NULL No
5 3 Yes
The idea is to put the row with ID 5 higher, the ID of 3 is unkown at this point. How Can i get the ID of the row with te first sortorder higher as the current?
Sample values: TomoveID = 5, Up = 1
After sorting the result shoud be:
ID SortOrder UseForSwap
1 1 Yes
2 NULL No
3 3 Yes
4 NULL No
5 2 Yes
Thanks in advance
You can search for a row with the biggest SortOrder that is less than SortOrder of ID 5 row in this way:
SELECT TOP 1
tbl.ID
FROM YourTable tbl
WHERE tbl.SortOrder < (SELECT SortOrder FROM YourTable tbl2 WHERE tbl2.ID = 5)
ORDER BY
tbl.SortOrder DESC
This is a bit of a weird question, and I know it would probably be easier to not do it in SQL, but it will make my life a lot easier.
Basically I have a single column result-set, and I need to turn that into 3 columns, not based on any criteria.
eg.
1
2
3
4
5
6
7
into:
1 2 3
4 5 6
7
It will always be a fixed 3 column result I need in this case.
Currently I am using a cursor and inserting into a table variable, which seems a bit terrible. There must be a better way.
Thanks
Try this:
declare #t table(n int)
insert #t(n) values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
select [0],[1],[2]
from
(
select n
, (ROW_NUMBER() over (order by n) - 1) % 3 c
, (ROW_NUMBER() over (order by n) - 1) / 3 r
from #t
) x
pivot (max(n) for c in ([0], [1], [2])) p
It's possible, but man is this an ugly requirement. This really belongs in the presentation tier, not in the sql.
WITH original As
(
SELEZCT MyColumn, row_number() over (order by MyColumn) as ordinal
FROM RestOfOriginalQueryHere
),
Grouped As
(
SELECT MyColumn, ordinal / 3 As row, ordinal % 3 As col
FROM original
)
SELECT o1.MyColumn, o2.MyColumn, o3.MyColumn
FROM grouped g1
LEFT JOIN grouped g2 on g2.row = g1.row and g2.col = 1
LEFT JOIN grouped g3 on g2.row = g1.row and g3.col = 2
WHERE g1.col = 0