SQL Select Counter by Group - sql

Here is the code I've written to create a scenario:
USE tempdb
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.Emp') AND type in (N'U'))
DROP TABLE Emp
GO
CREATE TABLE Emp(
EmpID Int Identity(10,1) Primary Key,
EmpGroupID Int)
GO
INSERT INTO Emp(EmpGroupID) VALUES(1000)
INSERT INTO Emp(EmpGroupID) VALUES(1000)
INSERT INTO Emp(EmpGroupID) VALUES(1000)
INSERT INTO Emp(EmpGroupID) VALUES(2000)
INSERT INTO Emp(EmpGroupID) VALUES(2000)
INSERT INTO Emp(EmpGroupID) VALUES(2000)
INSERT INTO Emp(EmpGroupID) VALUES(3000)
GO
SELECT * FROM Emp
ORDER BY EmpGroupID,EmpID
What I need is for each group to have a counter variable, incrementing by 1, such that all the rows for Group 1000 have counter=1, groupid=2000 has counter=2, groupid=3000 has counter=3.
SELECT ?,EmpID,EmpGroupID
FROM Emp
ORDER BY EmpGroupID,EmpID
-- The result I'm looking for is:
1,10,1000
1,11,1000
1,12,1000
2,13,2000
2,14,2000
2,15,2000
3,16,3000

You're describing a dense ranking of groups:
SELECT
DENSE_RANK() OVER (ORDER BY EmpGroupID) as Counter,
EmpID,
EmpGroupID
FROM Emp
ORDER BY EmpGroupID,EmpID
And here's some reference material: http://msdn.microsoft.com/en-us/library/ms189798.aspx

You mean, you need a query that produces textual output with the commas as shown?
Try:
SELECT Counter + ',' + EmpGroupID + ',' + EmpID
FROM Table
ORDER BY EmpGroupID

ORDER BY can have more than one clause
Try
SELECT Counter,EmpGroupID, EmpID
ORDER BY Counter,EmpGroupID, EmpID

Guessing from your description, do you want something like
SELECT EmpGroupID, EmpID, COUNT(1) AS Counter
FROM some-table-name
GROUP BY EmpGroupID, EmpID
ORDER BY COUNT(1), EmpGroupID, EmpID
That's for SQL Server - in other cases you may be able to say
ORDER BY Counter, EmpGroupID, EmpID

It took me a while to understand what you were asking. As I understand it, you want to create and populate the 'Counter' column based on the EmpGroupID? If so, then something like this:
SELECT EmpGroupID, EmpID,
(SELECT COUNT(*) +1
FROM [table]
WHERE t2.EmpGroupID < t1.EmpGroupID GROUP BY t2.EmpGroupID
) AS Counter
FROM [table] t1
ORDER BY EmpGroupID, EmpID

Try this:
SELECT DENSE_RANK() OVER (ORDER BY EmpID) as 'counter',GroupID
FROM Emp
ORDER BY counter, EmpGroupID

Related

How to get the each record with some condition

I have following data:
DECLARE #temp TABLE (
ID int
,sn varchar(200)
,comment varchar(2000)
,rownumber int
)
insert into #temp values(1,'sn1',NULL,1)
insert into #temp values(2,'sn1','aaa',2)
insert into #temp values(3,'sn1','bbb',3)
insert into #temp values(4,'sn1',NULL,4)
insert into #temp values(5,'sn2',NULL,1)
insert into #temp values(6,'sn2',NULL,2)
insert into #temp values(7,'sn2',NULL,3)
select * from #temp
And I want to output like this:
2 sn1 aaa 2
5 sn2 NULL 1
same sn, if comment have value, get this lower rownumber's record. For sn1, have two records with comment value, so here, get the the record with rownumber=2
If comment doesn't have value, get the lower rownumber's record. For sn2, get the record with rownumber=1
May I know how to write this SQL?
This is a prioritization query. I think row_number() is the simplest method:
select t.*
from (select t.*,
row_number() over (partition by sn
order by (case when comment is not null then 1 else 2 end),
rownumber
) as seqnum
from #temp t
) t
where seqnum = 1;
Here is a db<>fiddle.

SQL Insert into Temp Table With Serial Number

I have a simple SQL Query like:
Select Distinct GroupCode
Into #TempTable
From MyTable
SELECT * FROM #TempTable
drop Table #TempTable
And its OutPut is as
Now, I also want a Serial Number Column like 1,2,3.... there in the Out put.
How can I achieve that?
Thanks
Just add row_number():
select row_number() over (order by (select NULL)) as id, GroupCode
into #TempTable
from (select distinct GroupCode from MyTable) t;
select *
from #TempTable;
drop Table #TempTable;
You can explicitly create the temp table and add an IDENTITY column for your serial numbers, like so:
create table #tmp(id int identity(1,1), groupcode uniqueidentifier)
insert into #tmp (groupcode)
Select Distinct GroupCode
from mytable
select * from #tmp
order by id
drop table #tmp

Insert into table from another table after sorting data of first table

I am doing something like this in SP,
insert into #FilteredTbl select * from #MasterTbl
but now problem is that i want data of #MasterTbl sorted before adding into #FilteredTbl,
How can I do that ?
Maybe something like this:
INSERT INTO #FilteredTbl
SELECT * FROM #MasterTbl AS tbl
ORDER BY tbl.OrderbyColumn
Try following method to insert sort result into temp table. Use ROW_NUMBER to ORDER BY table result
DECLARE #FilteredTbl AS TABLE
(
RowID INT
[Column_1]
[Column_2]
.
.
)
insert into #FilteredTbl
select ROW_NUMBER()OVER(ORDER BY [ShortColumn]),[Field_1],[Field_2]... from #MasterTbl
You can use order by class in select statement
insert into #FilteredTbl
select * from #MasterTbl
order by <column name>
INSERT INTO #FilteredTbl SELECT * FROM #MasterTbl AS mtb ORDER BY mtb.OrderbyColumn [desc]
Here desc is optional if you want to order by your column in descending order than add ir otherwise no need to add
Please sort the table as you want before inserting into another table.
Like:
Select * From #MasterTbl m Order By m.ColumnName
then insert into your new table
Insert Into #FilterTbl Select * From #MasterTbl m Order By m.ColumnName [DESC]
You can also filter your #MasterTbl using Where Clause
You should add identity your table then It will sorted like that
CREATE TABLE #test (
s int IDENTITY (1, 1),
ID int,
Name varchar(50),
part int
);
INSERT INTO #test (ID,Name,Part)
SELECT ID, Name, Part FROM Table_1 ORDER BY ID DESC
SELECT * FROM #test

deleting duplicate rows?

i want to delete duplicate rows from my table on the basis of category ID, but don't want to delete all, i want to left one rows if there are more than one row with the same category ID.
this is my query i am making i need to change it.
delete from twinhead_tblcategory where categoryid in (select categoryid from twinhead_tblcategory group by categoryid having count(categoryid) > 1 )
For SQL Server you can do it:
WITH MyTableCTE (CategoryId, RowNumber)
AS
(
SELECT CategoryId, ROW_NUMBER() OVER (ORDER BY CategoryId) AS 'RowNumber'
FROM MyTable
)
Delete From MyTableCTE Where RowNumber > 1
Do a select distinct into a new table, delete the old one and rename the new one into old table name.
If your rows have a distinct id column, then this should work:
DELETE t1 FROM your_table t1, your_table t2
WHERE t1.column1 = t2.column1 AND t1.column2 = t2.column2
AND ... /* check equality of all relevant columns */
AND t1.id < t2.id
Check here for sql server - http://support.microsoft.com/kb/139444 - that should get you started.
This is probably heavy-handed but perhaps you could select distinct * into a temp table, then truncate the table, then insert into the table the contents of the temp table. Foreign key constraints may prevent this, though.
For SqlServer, you could use a cursor to loop through all items, ordered by that categoryID.
Is the current ID the same as the previous one? Then delete it, see example C of this article.
Else remember the ID for the next round.
You have several way for delete duplicate rows.
for my solutions , first consider this table for example
CREATE TABLE #Employee
(
ID INT,
FIRST_NAME NVARCHAR(100),
LAST_NAME NVARCHAR(300)
)
INSERT INTO #Employee VALUES ( 1, 'Vahid', 'Nasiri' );
INSERT INTO #Employee VALUES ( 2, 'name1', 'lname1' );
INSERT INTO #Employee VALUES ( 3, 'name2', 'lname2' );
INSERT INTO #Employee VALUES ( 2, 'name1', 'lname1' );
INSERT INTO #Employee VALUES ( 3, 'name2', 'lname2' );
INSERT INTO #Employee VALUES ( 4, 'name3', 'lname3' );
First solution : Use another table for duplicate rows.
SELECT DISTINCT *
FROM #Employee
SELECT * INTO #DuplicateEmployee
FROM #Employee
INSERT #DuplicateEmployee
SELECT DISTINCT *
FROM #Employee
BEGIN TRAN
DELETE #Employee
INSERT #Employee
SELECT *
FROM #DuplicateEmployee
COMMIT TRAN
DROP TABLE #DuplicateEmployee
SELECT DISTINCT *
FROM #Employee
Second solution :
SELECT DISTINCT * FROM #Employee
SELECT * INTO #DuplicateEmployee FROM #Employee
INSERT #DuplicateEmployee
SELECT ID,
FIRST_NAME,
LAST_NAME
FROM #Employee
GROUP BY
ID,FIRST_NAME,LAST_NAME
HAVING COUNT(*) > 1
BEGIN TRAN
DELETE #Employee
FROM #DuplicateEmployee
WHERE #Employee.ID = #DuplicateEmployee.ID
AND #Employee.FIRST_NAME = #DuplicateEmployee.FIRST_NAME
AND #Employee.LAST_NAME = #DuplicateEmployee.LAST_NAME
INSERT #Employee
SELECT *
FROM #DuplicateEmployee
COMMIT TRAN
DROP TABLE #DuplicateEmployee
SELECT DISTINCT * FROM #Employee
teared solution : use rowcount
SELECT DISTINCT *
FROM #Employee
SET ROWCOUNT 1
SELECT 1
WHILE ##rowcount > 0
DELETE #Employee
WHERE 1 < (
SELECT COUNT(*)
FROM #Employee a2
WHERE #Employee.ID = a2.ID
AND #Employee.FIRST_NAME = a2.FIRST_NAME
AND #Employee.LAST_NAME = a2.LAST_NAME
)
SET ROWCOUNT 0
SELECT DISTINCT *
FROM #Employee
Fourth solution : use Analytical Functions
SELECT DISTINCT *
FROM #Employee;
WITH #DeleteEmployee AS (
SELECT ROW_NUMBER()
OVER(PARTITION BY ID, First_Name, Last_Name ORDER BY ID) AS
RNUM
FROM #Employee
)
DELETE
FROM #DeleteEmployee
WHERE RNUM > 1
SELECT DISTINCT *
FROM #Employee
Fifth solution : Use identity field
SELECT DISTINCT *
FROM #Employee;
ALTER TABLE #Employee ADD UNIQ_ID INT IDENTITY(1, 1)
DELETE
FROM #Employee
WHERE UNIQ_ID < (
SELECT MAX(UNIQ_ID)
FROM #Employee a2
WHERE #Employee.ID = a2.ID
AND #Employee.FIRST_NAME = a2.FIRST_NAME
AND #Employee.LAST_NAME = a2.LAST_NAME
)
ALTER TABLE #Employee DROP COLUMN UNIQ_ID
SELECT DISTINCT *
FROM #Employee
and end of all solution use this command
DROP TABLE #Employee
Source of my answer is this site

T-SQL: How to make cell-values unique?

If I have a table where the cells in a column should not have the same values, how do I check this and update? (I know I can set constraints in the settings, but I don't want to do that.)
Say the column name is called unique hash name and contains
Peter
Peter
Peter
Dave
Dave
and so on. I want that to transform to:
Peter
Peter1
Peter2
Dave
Dave1
What is the T-SQL for SQL Server to do that?
Update: For clarity's sake, let's call the table "Persons" and the cell I want unique "UniqueName". Could you make it a SELECT-statement, so I can test the result before updating. And I am using SQL Server 2005 and above.
EDIT: I've changed the query to use your field names and added a "select-only" query for you to preview.
This is actually pretty easy to do... just use ROW_NUMBER() with a PARTITION clause:
UPDATE Persons SET UniqueName = temp.DeDupded FROM
(SELECT ID,
CASE WHEN ROW_NUMBER() OVER
(PARTITION BY UniqueName ORDER BY UniqueName) = 1 THEN UniqueName
ELSE UniqueName + CONVERT(VARCHAR, ROW_NUMBER()
OVER (PARTITION BY UniqueName ORDER BY UniqueName)-1) END AS DeDupded
FROM Persons) temp
WHERE Persons.ID = temp.ID
If you want a "select-only", then here you go:
SELECT ID,
CASE WHEN ROW_NUMBER() OVER
(PARTITION BY UniqueName ORDER BY UniqueName) = 1 THEN UniqueName
ELSE UniqueName + CONVERT(VARCHAR, ROW_NUMBER()
OVER (PARTITION BY UniqueName ORDER BY UniqueName)-1) END AS DeDupded
FROM Persons
EDIT Again: If you're looking for a SQL Server 2000 Solution...
CREATE TABLE #Persons ( ID INT IDENTITY(1, 1), UniqueName VARCHAR(100) )
INSERT INTO #Persons VALUES ('Bob')
INSERT INTO #Persons VALUES ('Bob')
INSERT INTO #Persons VALUES ('Bob')
INSERT INTO #Persons VALUES ('John')
INSERT INTO #Persons VALUES ('John')
SELECT
ID,
CASE WHEN Position = 0 THEN UniqueName
ELSE UniqueName + (CONVERT(VARCHAR, Position))
END AS UniqueName
FROM
(SELECT
ID,
UniqueName,
(SELECT COUNT(*) FROM #Persons p2 WHERE
p1.UniqueName = p2.UniqueName AND p1.ID > p2.ID) AS Position
FROM
#Persons p1) _temp
DROP TABLE #Persons
This feels like a pretty clear use-case for a trigger (insert,update).