I am trying the following:
update [Employees] set Last_User =
(select top 1 name from
(select 'John' as name
union select 'Tim' as name
union select 'Jane' as name
union select 'Jack' as name
union select 'Steve' as name
union select 'Ann' as name
)
as names order by newid())
but keep getting the same name for all rows. how can I make it vary?
Note: names are entered in query and do not come from another table.
Thanks
You are trying to update the whole column instead of updating each row, hence the first value which is getting generated is updated to all the rows, you can do the intended task by using T-SQL
DECLARE #counter int = 1
WHILE #counter <= (SELECT COUNT(1) FROM [Employees]) --or any speific row set you want to modify
BEGIN
UPDATE a
set Last_User =
(SELECT top 1 name from
(SELECT 'John' as name
UNION SELECT 'Tim' AS name
UNION SELECT 'Jane' AS name
UNION SELECT 'Jack' AS name
UNION SELECT 'Steve' AS name
UNION SELECT 'Ann' AS name
)
AS names ORDER BY NEWID())
FROM (SELECT *,ROW_NUMBER() OVER (ORDER BY Last_User)rnum FROM [Employees])a
WHERE a.rnum = #counter
SET #counter = #counter + 1
END
You can try this approach:
declare #Employees table (last_user nvarchar(100))
insert #Employees values('a')
insert #Employees values('b')
insert #Employees values('c')
declare #temp table(name nvarchar(100))
insert into #temp values('John')
insert into #temp values('Tim')
insert into #temp values('Jane')
insert into #temp values('Jack')
insert into #temp values('Steve')
insert into #temp values('Ann')
update #Employees set Last_User =
(select top 1 name from
#temp as names order by newid())
select * from #Employees
Related
I have a scenario wherein I need to find the ID which only has start and END in it. Below is the table for reference.
Declare #T Table ( ID int, Name varchar(100))
Insert into #T values (1,'Start')
Insert into #T values (1,'END')
Insert into #T values (1,'Stuart')
Insert into #T values (1,'robin')
Insert into #T values (2,'Start')
Insert into #T values (2,'END')
Insert into #T values (3,'Start')
Insert into #T values (4,'END')
I want the Output as:
ID Name
2 Start
2 END
I want those ID which only has start and end in it.
What I tried so far:
SELECT * FROM #T t
WHERE EXISTS (SELECT * FROM #T WHERE id = t.id AND name = 'start')
AND EXISTS (SELECT * FROM #T WHERE id = t.id AND name = 'END')
But my query is giving ID 1 as well.
Can someone please help me rectify the problem.
I presume your issue is that record 1 has a 'Stuart' in it too?
As such, you can do a similar check in the WHERE e.g.,
SELECT * FROM #T t
WHERE EXISTS (SELECT * FROM #T WHERE id = t.id AND name = 'start')
AND EXISTS (SELECT * FROM #T WHERE id = t.id AND name = 'END')
AND NOT EXISTS (SELECT * FROM #T WHERE id = t.id AND name NOT IN ('start','END'))
Note that you may want to consider
What happens if you have two 'start' rows or two 'end' rows (e.g., start-start-end)? Can you even have two 'start' rows (e.g., start-start)?
What happens if you have a blank/NULL (e.g., start-NULL-end)?
EDIT: removed 'What happens if they're out of order (e.g., end-start)?' as a question as there is no sorting in the data at all (e.g., not even an implicit sort).
You can go for CTE to get group wise count and total count as 2.
Declare #T Table ( ID int, Name varchar(100))
Insert into #T values (1,'Start')
Insert into #T values (1,'END')
Insert into #T values (1,'Stuart')
Insert into #T values (1,'robin')
Insert into #T values (2,'Start')
Insert into #T values (2,'END')
Insert into #T values (3,'Start')
Insert into #T values (4,'END')
;WITH CTE_Total_StartEnd AS
(
select id, count(*) AS Total_Cnt
, COUNT( case when Name IN ('Start') THEN 1 END) as start_cnt
, COUNT( case when Name IN ('End') THEN 1 END) as end_cnt
from #t
group by id
having COUNT( case when Name IN ('Start') THEN 1 END) =1 and
COUNT( case when Name IN ('End') THEN 1 END) = 1 and
count(*) = 2
)
SELECT t.* from #t t
inner join CTE_Total_StartEnd as c
ON c.id = t.id
+----+-------+
| ID | Name |
+----+-------+
| 2 | Start |
| 2 | END |
+----+-------+
You can do this by using group by function also like below
WITH cte AS
(
SELECT 1 AS id , 'Start' AS name
UNION ALL
SELECT 1 AS id ,'END' AS name
UNION ALL
SELECT 1 AS id ,'Stuart' AS name
UNION ALL
SELECT 1 AS id ,'robin' AS name
UNION ALL
SELECT 2 AS id ,'Start' AS name
UNION ALL
SELECT 2 AS id ,'END' AS name
UNION ALL
SELECT 3 AS id ,'Start' AS name
UNION ALL
SELECT 4 AS id ,'END' AS name
)
SELECT T.ID,SUM(T.VAL)AS SUM
FROM
(
SELECT id,name , CASE WHEN name='Start' THEN 1
WHEN name='END' THEN 2
ELSE 3
END AS VAL
FROM cte
)T
GROUP BY T.ID
HAVING SUM(T.VAL) =3
could you please try this? Pls note i added collate command in the end of sql.
SQL Server check case-sensitivity?
SELECT * FROM #T t
WHERE EXISTS (SELECT * FROM #T WHERE id = t.id AND name = 'start' COLLATE SQL_Latin1_General_CP1_CS_AS)
AND EXISTS (SELECT * FROM #T WHERE id = t.id AND name = 'END' COLLATE SQL_Latin1_General_CP1_CS_AS)
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.
I have a dataset like:
type seqID text
A 1 Text1a
A 2 Text2a
A 3 Text3a
B 1 Text1b
B 2 Text2b
How do I get the row back by type with the highest seqID grouped by type? So in the above example I would want the row that has A, 3, Text3a and B, 2, Text2b returned.
SELECT *
FROM tmp t1
WHERE NOT EXISTS
(SELECT 1 FROM tmp t2 WHERE t1.type = t2.type AND t2.seqID > t1.seqID)
It shouldn't exists any other row with the same type and higher seqID.
You kind of need an ID, but since "Text" seems unique for this example
CREATE TABLE #TMP
(type VARCHAR(3), seqID INT, [text] varchar(256))
insert #TMP values ('A' , 1 , 'Text1a')
insert #TMP values ('A' , 2 , 'Text2a')
insert #TMP values ('A' , 3 , 'Text3a')
insert #TMP values ('B' , 1 , 'Text1b')
insert #TMP values ('B' , 2 , 'Text2b')
SELECT * FROM #TMP T
where [text] IN
(SELECT TOP 1 [text] FROM #TMP t2 WHERE t.type = t2.type ORDER BY t2.seqID DESC)
SELECT tbl.*
FROM
( SELECT type, MAX(seqID)
FROM tbl
GROUP BY type) maxes
WHERE
tbl.type= maxes.type AND
tbl.seqID= maxes.seqID
SELECT t.* FROM
(
SELECT type, MAX(seqID) as maxId
FROM Table
GROUP BY type
) m
INNER JOIN Table t ON m.maxId = t.seqId
Using CTE
;WITH maxIds(maxId)
AS
(
SELECT type, MAX(seqID) as maxId
FROM Table
GROUP BY type
)
SELECT t.* FROM
Table t
INNER JOIN maxIds m ON m.maxId = t.seqID
If you are on SQL Server 2005+, you could use a ranking function (more specifically, ROW_NUMBER()):
SELECT
type,
seqID,
text
FROM (
SELECT
*,
rnk = ROW_NUMBER() OVER (PARTITION BY type ORDER BY seqID DESC)
FROM atable
) s
WHERE rnk = 1
create table #tlb1(
[type] VARCHAR(3), seqID INT, [text] varchar(max)
)
declare #type varchar(3), #text varchar(max);
declare #seqID int;
declare seq_cursor cursor for
select [type], max(seqID) from tbl group by [type]
open seq_cursor
fetch next from seq_cursor into #type,#seqID
while(##fetch_status=0)
begin
set #text= (select [text] from tbl where [type]=#type and seqID=#seqid);
insert into #tlb1 values (#type, #seqID,#text);
fetch next from seq_cursor into #type,#seqID
end
select * from #tlb1
close seq_cursor
deallocate seq_cursor
truncate table #tlb1
Try:
SELECT type, max(seqID),text
FROM 'db'
GROUP BY type
As easy as that.
EDITED solution. Consider this a psuedo-code (since I am not familiar with SQL server syntax):
SELECT a.type, a.seqID, a.text FROM table a
JOIN
(SELECT type, max(seqID) seqID FROM table GROUP BY type) b
ON a.seqID = b.seqID AND a.type=b.type
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
SELECT id, EmpNo
FROM EmployeesTable
EmpNo can be the same for 1 or more records in the results of the above query. I now want to add another column derived from EmpNo(lets call it EmpNo2) but only returning distinct values of EmpNo.
For example if the above query returns 100 records but there are 69 distinct EmpNo values and i modify the query to
SELECT id, EmpNo, Distinct EmpNo2
FROM EmployeesTable EmpNo
,
i want all the 100 rows to be returned but the last column EmpNo2 should return 69 distinct values of EmpNo field.
But as already know, using distinct in that way results into an error but i want to implement such functionality - and a subquery is not helping.
SAMPLE REQUIRED RESULTS
ID EmpNo EmpNo2
1 0T4/HR 0T4/HR
1 0T4/HR 2VP/E
1 0T4/HR xT9/67
1 0T4/HR
1 0T4/HR
2 2VP/E
2 2VP/E
2 2VP/E
2 2VP/E
2 2VP/E
3 XT9/67
3 XT9/67
3 xT9/67
3 XT9/67
How about:
Select id, empno, empno2
from employeestable left outer join (
SELECT min([id]) as minid
,[empno] empno2
FROM [EmployeesTable]
group by empno) etab2 on employeestable.id = etab2.minid
You're saying a subquery won't work, though - why not?
Your requirement is not clear and I also have very little information. Following is what you need. This can be even better but it is just a try.
declare #temp table
(
uniqueid int identity(1, 1),
id int,
empno varchar(50),
empno2 varchar(50)
)
insert into #temp select 1, '0T4/HR', null
insert into #temp select 1, '0T4/HR' , null
insert into #temp select 1 , '0T4/HR' , null
insert into #temp select 1, '0T4/HR' , null
insert into #temp select 1, '0T4/HR' , null
insert into #temp select 2, '2VP/E' , null
insert into #temp select 2, '2VP/E' , null
insert into #temp select 2, '2VP/E' , null
insert into #temp select 2, '2VP/E' , null
insert into #temp select 2, '2VP/E' , null
insert into #temp select 3, 'XT9/67' , null
insert into #temp select 3, 'XT9/67' , null
insert into #temp select 3, 'xT9/67' , null
insert into #temp select 3, 'XT9/67' , null
SELECT ROW_NUMBER() OVER (ORDER BY id) AS id, empno into #temp FROM #temp group by empno, id
update #temp set empno2 = t2.empno
from #temp t inner join #temp t2 on t.uniqueid = t2.id
select * from #temp
drop table #temp