SQL Server - Sorting column based on string and number - sql

I have a table with one column which contains combination of string and number like as shown below. I need to sort the name column in descending or ascending but the problem is when I use ORDER BY it is not sorting as expected
My query is like as shown below
SELECT * FROM test ORDER BY `name` ASC
My expected result is like as shown blow
employee1
employee2
employee3
employee6
employee6
employee10
employee11
employee12
employee17
employee82
employee100
employee111
employee129
employee299
Can anyone please help me on this

You can try below by only extracting the number part from the field
SELECT * FROM test
ORDER BY cast(replace(`name`,'employee','') as int) ASC

Please try the code below:
-- ASSUMES NUMBERS ARE IN THE LAST CHARACTER
-- WONT WORK IF NUMBER IS THERE IN THE MIDDLE
DROP TABLE IF EXISTS #data
select
Name = REPLACE(name,' ','')
,NameWithNum = REPLACE(name,' ','') + cast(object_id as varchar(100))
INTO #data
from sys.tables
SELECT
NameWithNum
,NameRemovedNumbers= SUBSTRING(NameWithNum, PATINDEX('%[0-9]%', NameWithNum), LEN(NameWithNum))
from #data
ORDER BY Name,SUBSTRING(NameWithNum, PATINDEX('%[0-9]%', NameWithNum), LEN(NameWithNum))

Since the number always in the end, you can do as
WITH CTE AS
(
SELECT 'employee1' Name
union all select 'employee2'
union all select 'employee3'
union all select 'employee6'
union all select 'employee6'
union all select 'employee10'
union all select 'employee11'
union all select 'employee12'
union all select 'employee17'
union all select 'employee82'
union all select 'employee100'
union all select 'employee111'
union all select 'employee129'
union all select 'employee299'
)
SELECT Name
FROM CTE
ORDER BY CAST(SUBSTRING(Name, PATINDEX('%[^a-z, '' '']%', Name), LEN(Name)) AS INT)
--OR PATINDEX('%[0-9]%', Name)
Or
WITH CTE AS
(
SELECT 'The First Employee 1' Name
union all select 'The Second One 2'
union all select 'Employee Number 4'
union all select 'Employee Number 3'
)
SELECT Name
FROM CTE
ORDER BY CAST(SUBSTRING(Name, PATINDEX('%[0-9]%', Name), LEN(Name)) AS INT)
Here is a Live Demo where you can change the strings and see the results.
Finnaly, I would note to the real problem, which is a table with just one column and no PK.

The "base" part of the name is the same. So, you can order by the length and then the name:
SELECT t.*
FROM test t
ORDER BY LEN(name), name;

Related

Perform a function after union of two tables

I have two tables that I want to union together then perform some math functions on the combined table.
I know how to do the math for each separate table, but throwing in a union table to go off of is out of my league.
Here's the math for one table using column header "UnitsReceived" and "AsnPsUnits"
The other table would have headers: "cUnitsReceived" and "cAsnPsUnits"
select VendName,
1-abs(((cast(sum(UnitsReceived) as decimal(5,0))) - (cast(sum(AsnPsUnits) as decimal(5,0)))) /(cast(sum(AsnPsUnits) as decimal(5,0)))) as ASNpsAcc
from VenTest2
where ID<20
group by VendName
How would I perform this function after the union of two tables?
You'll need to get the unioned tables into some table object before performing your function. This could be done using:
A Common Table Expression
with cte as (
select ID, VALUE from A
union all
select ID, VALUE from B
)
select
*
,myfunction(VALUE) as MyFunctionResult
from
cte
A temp table
select ID, VALUE into #myTempTable from A
insert into #myTempTable select ID, VALUE from B
select
*
,myfunction(VALUE) as MyFunctionResult
from
#myTempTable
A table variable
declare #myTableVariable table (ID int, VALUE decimal)
insert into #myTableVariable
select ID, VALUE from A
union all
select ID, VALUE from B
select
*
,myfunction(VALUE) as MyFunctionResult
from
#myTableVariable
A sub query
select
*
,myfunction(VALUE) as MyFunctionResult
from
(
select ID, VALUE from A
union all
select ID, VALUE from B
) mySubQuery
This will help with the subq being the union
select VendName,
1-abs(((cast(sum(UnitsReceived) as decimal(5,0))) - (cast(sum(AsnPsUnits) as decimal(5,0)))) /(cast(sum(AsnPsUnits) as decimal(5,0)))) as ASNpsAcc
from
(
select ID, UnitsReceived, AsnPsUnits from VenTest2 where ID<20
union
select ID1, UnitsReceived1, AsnPsUnits1 from VenTest1
)a
group by VendName
This is not the way, brothers:
select VendName,
1-abs(((cast(sum(UnitsReceived) as decimal(10,2))) - (cast(sum(AsnPsUnits) as decimal(10,2)))) /(cast(sum(AsnPsUnits) as decimal(10,2)))) as ASNpsAcc
from VenTest2
where ID<10
group by VendName
union
select cVendName,
1-abs(((cast(sum(cUnitsReceived) as decimal(10,2))) - (cast(sum(casnpsunits) as decimal(10,2)))) /(cast(sum(cAsnPsUnits) as decimal(10,2)))) as ASNpsAcc
from CTest
where id <10
group by cvendname

I want to retrieve max value from two column - SQL table

Please find attached image for table structure
You could try using UNION ALL for build a unique column result and select the max from this
select max(col)
from (
select col1 col
from trans_punch
union all
select col2
from trans_punch) t
You can use a common table expression to union the columns, then select the max.
;with cteUnionPunch(Emp_id, both_punch) AS
(
SELECT Emp_id, In_Punch FROM trans_punch
UNION ALL
SELECT Emp_id, Out_Punch FROM trans_punch
)
SELECT Emp_id, max(both_punch) FROM cteUnionPunch GROUP BY Emp_id
You can use apply :
select tp.Emp_id, max(tpp.Punchs)
from trans_punch as tp cross apply
( values (In_Punch), (Out_Punch) ) tpp(Punchs)
group by tp.Emp_id;

Convert from single column to multiple Column in sql Server

i have tried with below code. but i didnt get ouput as per multiple column.
select Name=stuff((select ','+
name from Input t1 WHERE t1.Name=t2.name for xml path('')),1,9,''),NAME
=stuff((select ','+
name from Input t1 WHERE t1.Name=t2.name for xml path('')),1,1,'')FROM
Input T2
GROUP BY NAME
I have separated the character and numeric parts of the given string in CTE and used a simple group by and sum clause on that.
;With CTE
As
(
Select
Left(Names, 1) As String,
SUBSTRING(Names, 2, Len(Names) - 1) As Number
From SeparateColumns
)
Select
String,
Sum(Cast(Number As Int)) As SumOfDigits
From CTE
Group By String
Order By String;
Assuming you will have single character in your column, the following code works
CREATE TABLE #TEMP_SPLIT
(VALUE VARCHAR(25))
INSERT INTO #TEMP_SPLIT
SELECT 'A10'
UNION
SELECT 'B20'
UNION
SELECT 'A30'
UNION
SELECT 'B40'
UNION
SELECT 'A10'
UNION
SELECT 'C1'
SELECT c, sum(tot)
FROM
(
SELECT SUBSTRING(VALUE,1,1) c ,CONVERT(FLOAT,SUBSTRING(VALUE,2,LEN (VALUE)-1)) Tot
FROM #TEMP_SPLIT
)T
GROUP BY C
DROP TABLE #TEMP_SPLIT
If the names column is always in the specified format, then use LEFT function to extract the character part and RIGHT function to extract the digits part and use these two in the sub-query and use GROUP BY clause and SUM function.
Query
select t.col_a as [string character],
sum(cast(t.col_b as int)) as [sum of digits] from(
select left(names, 1) as col_a,
right(names, len(names) - 1) as col_b
from [your_table_name]
) t
group by t.col_a;
Find a example here
You could use PATINDEX() with SUBSTRING() function if names always in this specified format
select A.CHAR [Strings], SUM(CAST(A.VALUE AS INT)) [Sum] from
(
SELECT SUBSTRING(Name, 1, PATINDEX('%[^A-Z]%', Name)-1) [CHAR], SUBSTRING(Name, PATINDEX('%[0-9]%', Name), len(Name)) [VALUE] FROM <table>
) a GROUP BY A.CHAR
Here's simple solution using subquery and group by clause:
select [StringChar], SUM([Number]) from (
select SUBSTRING(Names, 1, 1) as [StringChar],
convert(int, SUBSTRING(Names, 2, LEN(Names))) as [Number]
from [Input]
) as a group by [StringChar]

BigQuery - Concatenate multiple rows into a single row

I have a BigQuery table with 2 columns:
id|name
1|John
1|Tom
1|Bob
2|Jack
2|Tim
Expected output: Concatenate names grouped by id
id|Text
1|John,Tom,Bob
2|Jack,Tim
For BigQuery Standard SQL:
#standardSQL
--WITH yourTable AS (
-- SELECT 1 AS id, 'John' AS name UNION ALL
-- SELECT 1, 'Tom' UNION ALL
-- SELECT 1, 'Bob' UNION ALL
-- SELECT 2, 'Jack' UNION ALL
-- SELECT 2, 'Tim'
--)
SELECT
id,
STRING_AGG(name ORDER BY name) AS Text
FROM yourTable
GROUP BY id
Optional ORDER BY name within STRING_CONCAT allows you to get out sorted list of names as below
id Text
1 Bob,John,Tom
2 Jack,Tim
For Legacy SQL
#legacySQL
SELECT
id,
GROUP_CONCAT(name) AS Text
FROM yourTable
GROUP BY id
If you would need to output sorted list here, you can use below (formally - it is not guaranteed by BigQuery Legacy SQL to get sorted list - but for most practical cases I had - it worked)
#legacySQL
SELECT
id,
GROUP_CONCAT(name) AS Text
FROM (
SELECT id, name
FROM yourTable
ORDER BY name
)
GROUP BY id
You can use GROUP_CONCAT
SELECT id, GROUP_CONCAT(name) AS Text FROM <dataset>.<table> GROUP BY id

SQL Server query for getting single value from each column into a single column

I'll start directly by explaining with an example. Suppose I have a table which has 3 columns as shown.
Now what I am trying to achieve is, I want the first values of each individual column into a single column. So it would be something like this,
I have tried a few queries here including using TOP 1 and other incorrect ways. But I am still missing something here to achieve the exact output.
Need some guidance here on how to achieve this. Thank you.
SAMPLE TABLE
SELECT * INTO #TEMP
FROM
(
SELECT 1 BATCH_ID,'AAA' ASSIGNMENTTITLE,'FILE' ASSIGNMENTTYPE
UNION ALL
SELECT 1,'AAA1','FILE'
UNION ALL
SELECT 1,'AAA','FILE'
)TAB
If you need the second row specifically you can do the below
QUERY
;WITH CTE AS
(
-- Order row according to default format
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO,*
FROM #TEMP
)
SELECT CAST(BATCH_ID AS VARCHAR(20)) FROM CTE WHERE RNO=2
UNION ALL
SELECT ASSIGNMENTTITLE FROM CTE WHERE RNO=2
UNION ALL
SELECT ASSIGNMENTTYPE FROM CTE WHERE RNO=2
Click here to view result
UPDATE
Since there are 3 items in each record, it can be puzzled unless and otherwise an a column is for each items in a record.
;WITH CTE AS
(
-- Order row according to default format
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO,*
FROM #TEMP
)
SELECT CAST(BATCH_ID AS VARCHAR(20)),RNO
FROM CTE
UNION ALL
SELECT ASSIGNMENTTITLE,RNO
FROM CTE
UNION ALL
SELECT ASSIGNMENTTYPE,RNO
FROM CTE
ORDER BY RNO
Click here to view result
You can use the concat() function to create a column consisting of all the desired values
More info here
Simply you can try this. If want specific for a row use rowid. For all columns Use unpivot
create table #temp(id int, name varchar(100), title varchar(100))
insert into #temp values(1,'aaa','file')
insert into #temp values(1,'aaas','filef')
insert into #temp values(1,'aaaww','filefs')
select * from #temp
select top 1 cast(id as varchar) title from #temp
union
select top 1 name from #temp
union
select top 1 title from #temp
drop table #temp
This might help you
select top 1 convert(varchar(10), batch_id) ASSIGNMENTTITLE from table
union all
select top 1 ASSIGNMENTTITLE from table
union all
select top 1 ASSIGNMENTTYPE from table
If this is really what you want: "I want the first values of each individual column into a single column" it would be:
select ASSIGNMENTTITLE
from (
select min(convert(varchar(10), batch_id)) ASSIGNMENTTITLE,
1 ColOrder from table
union all
select min(ASSIGNMENTTITLE),
2 ColOrder from table
union all
select min(ASSIGNMENTTYPE),
3 ColOrder from table
) as data
order by ColOrder