Selection One Entry Only As Non Zero In SQl Select - sql

I have a scenario where I have to select multiple rows from table, I have multiple rows of one record but with different status,
at times I have two identical rows with identical data for status < for that case I canted to select Non zero for the first occurrence and set 0 for the remaining occurrences.
Below is the Image to show and I have marked strike-out and marked 0 for the remaining occurrence.
And body could suggest better SQL Query:
Here is the Query: I am getting zero value for status 1 for ID =1 but I need to show first as regular and then 0 if that status repeats again.
CREATE TABLE #Temp
(ID INT,
ItemName varchar(10),
Price Money,
[Status] INT,
[Date] Datetime)
INSERT INTO #Temp VALUES(1,'ABC',10,1,'2014-08-27')
INSERT INTO #Temp VALUES(1,'ABC',10,2,'2014-08-27')
INSERT INTO #Temp VALUES(1,'ABC',10,1,'2014-08-28')
INSERT INTO #Temp VALUES(2,'DEF',25,1,'2014-08-26')
INSERT INTO #Temp VALUES(2,'DEF',25,3,'2014-08-27')
INSERT INTO #Temp VALUES(2,'DEF',25,1,'2014-08-28')
INSERT INTO #Temp VALUES(3,'GHI',30,1,'2014-08-27')
SELECT CASE WHEN Temp.Status = 1 THEN
0
ELSE
Temp.Price END AS Price,
* FROM (SELECT * FROM #Temp) Temp
DROP TABLE #Temp
Here is the result:

You might modify your inner select using Row_Number() and set price to Zero for RowNumber > 1.
SELECT CASE WHEN Temp.RowNumber > 1 THEN
0
ELSE
Temp.Price END AS Price,
* FROM (
SELECT *,Row_Number() over (PARTITION by ID,Status ORDER BY ID,Date) AS 'RowNumber'
FROM #Temp
) Temp
Order by ID,Date

You can try this:
;WITH DataSource AS
(
SELECT RANK() OVER (PARTITION BY [ID], [ItemName], [Price], [Status] ORDER BY Date) AS [RankID]
,*
FROM #Temp
)
SELECT [ID]
,[ItemName]
,IIF([RankID] = 1, [Price], 0)
,[Status]
,[Date]
FROM DataSource
ORDER BY [ID]
,[Date]
Here is the output:

please try this below code . it is working for me.
CREATE TABLE #Temp
(ID INT,
ItemName varchar(10),
Price Money,
[Status] INT,
[Date] Datetime)
INSERT INTO #Temp VALUES(1,'ABC',10,1,'2014-08-27')
INSERT INTO #Temp VALUES(1,'ABC',10,2,'2014-08-27')
INSERT INTO #Temp VALUES(1,'ABC',10,1,'2014-08-28')
INSERT INTO #Temp VALUES(2,'DEF',25,1,'2014-08-26')
INSERT INTO #Temp VALUES(2,'DEF',25,3,'2014-08-27')
INSERT INTO #Temp VALUES(2,'DEF',25,1,'2014-08-28')
INSERT INTO #Temp VALUES(3,'GHI',30,1,'2014-08-27')
select *,case when a.rn=1 and status!=2 then price else 0 end as price from
(select *,ROW_NUMBER() over(partition by status,date order by date asc) rn from #Temp) a
order by ItemName asc

You can do this with UNION:
SELECT * FROM #Temp t
WHERE NOT EXISTS
(SELECT * FROM #Temp
WHERE t.id = id and t.status = status and t.date < date)
UNION ALL
SELECT ID, ItemName, 0 as Price, status, date
WHERE EXISTS
(SELECT * FROM #Temp
WHERE t.id = id and t.status = status and t.date < date)
Or subquery:
SELECT CASE
WHEN (SELECT COUNT(*)
FROM #Temp
WHERE t.id = id and t.status = status
and t.date > date) > 1 THEN 0 ELSE price END as NewPrice, t.*
FROM #Temp t
Or possibly RANK() function:
SELECT CASE
WHEN RANK() OVER (PARTITION BY id, status ORDER BY date) > 1
THEN 0 ELSE Price END,
t.*
FROM #Temp t

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.

INSERT INTO #tmp from CTE query

I want to be able to insert the results of this CTE query into a temp table so I can sum the Total column.
CREATE TABLE #tmp
(
SerialNumber NVARCHAR(50),
StartDateTime NVARCHAR(50),
EndDateTime NVARCHAR(50),
Total NVARCHAR(50)
)
;WITH cte1 AS
(
SELECT
*,
CASE
WHEN Temperature > #maxthreshold AND LAG(Temperature) OVER (PARTITION BY SerialNumber ORDER BY CombineDateTime) IS NULL THEN 1
WHEN Temperature <= #maxthreshold AND LEAD(Temperature) OVER (PARTITION BY SerialNumber ORDER BY CombineDateTime) > #maxthreshold THEN 1
WHEN Temperature <= #maxthreshold AND LAG(Temperature) OVER (PARTITION BY SerialNumber ORDER BY CombineDateTime) > #maxthreshold THEN 1
END AS chg
FROM
[RawData]
WHERE
SerialNumber = #_Serial
AND CombineDateTime BETWEEN #_DateFrom AND #_DateTo
), cte2 AS
(
SELECT
*,
SUM(chg) OVER (PARTITION BY SerialNumber ORDER BY CombineDateTime) AS grp
FROM
cte1
)
INSERT INTO #tmp
SELECT
SerialNumber,
MIN(CombineDateTime) AS StartDateTime,
MAX(CombineDateTime) AS EndDateTime,
DATEDIFF(SECOND, MIN(CombineDateTime), MAX(CombineDateTime)) / 60.0 AS 'Total'
FROM
cte2
GROUP BY
SerialNumber, grp
HAVING
MAX(Temperature) > #maxthreshold)
SELECT *
FROM #tmp
DROP TABLE #tmp
I have tried putting the insert in various places, but it does not insert, I have tried the following answers. I am confused as to why the insert won't work as it is outside of the recursion.
Answer 1
Answer 2
TIA

Finding and Deleting duplicate rows in table where multiple occurances of records is allowed [duplicate]

This question already has answers here:
How can I remove duplicate rows?
(43 answers)
Closed 9 years ago.
I have a table that I need to delete duplicates. However, the table is designed so that each customer can have identical items. Here is a screen shot for example:
When I try to delete duplicates I also get Book Number that are the same for both customer.
The Green area shows actual duplicates, however the blue shows books that are not duplicate because customers can borrow the same books.
How do I delete only where the row is the same for each customer? So the green area.
Here is my code: It does not work if both customer has the same Book number.
WITH CTE AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY BookNumber ORDER BY BookNumber DESC) AS DUPS
FROM Store.Books
)
SELECT * FROM CTE WHERE DUPS > 1
the below query should give you a list of all the duplicate booknumbers with the customerIDs, all you need to do is a simple delete statement with the results to remove the duplicate records
SELECT count(bookNumber), booknumber, customerID FROM TableName GROUP BY booknumber, customerID having count(booknumber)> 1
WITH CTE AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY BookNumber, Customerid ORDER BY BookNumber) AS DUPS
FROM Store.Books
)
SELECT * FROM CTE WHERE DUPS > 1
-- if you want to delete, replace last line with this:
--DELETE FROM CTE WHERE DUPS > 1
I should mention that order by booknumber desc wasn't necessary so I removed the 'desc' part
Brothers, This is one of the way to find out duplicates data, try it=)
DECLARE #tempTable TABLE(
CustomerID SMALLINT,
BookLoan NVARCHAR(255),
BookNumber INT,
BookAuthor NVARCHAR(255)
)
INSERT INTO #tempTable Values(112,'Clash Of Titans',12345,'Dick VanDyke ')
INSERT INTO #tempTable Values(112,'Clash Of Titans',12345,'Dick VanDyke ')
INSERT INTO #tempTable Values(112,'Clash Of Titans',23457,'Dick VanDyke ')
INSERT INTO #tempTable Values(112,'History of Soda',99899,'Brian Adams ')
Select *,Count(*) 'Occurrance' From #tempTable Group by
CustomerID,BookLoan,BookNumber,BookAuthor having count(*) > 1
Delete from #temptable
where CustomerID = (Select customerID From #tempTable Group by
CustomerID,BookLoan,BookNumber,BookAuthor having count(*) > 1)
AND BookLoan = (Select BookLoan From #tempTable Group by
CustomerID,BookLoan,BookNumber,BookAuthor having count(*) > 1)
AND BookNumber = (Select BookNumber From #tempTable Group by
CustomerID,BookLoan,BookNumber,BookAuthor having count(*) > 1)
AND BookAuthor = (Select BookAuthor From #tempTable Group by
CustomerID,BookLoan,BookNumber,BookAuthor having count(*) > 1)
Select * from #tempTable
Or alternative way as below here
DECLARE #tempTable TABLE(
CustomerID SMALLINT,
BookLoan NVARCHAR(255),
BookNumber INT,
BookAuthor NVARCHAR(255)
)
INSERT INTO #tempTable Values(112,'Clash Of Titans',12345,'Dick VanDyke ')
INSERT INTO #tempTable Values(112,'Clash Of Titans',12345,'Dick VanDyke ')
INSERT INTO #tempTable Values(112,'Clash Of Titans',23457,'Dick VanDyke ')
INSERT INTO #tempTable Values(112,'History of Soda',12345,'Brian Adams ')
;WITH CTE AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY CustomerID, BookLoan,BookNumber,BookAuthor
ORDER BY BookNumber) AS DUPS
FROM #tempTable
)
DELETE FROM #tempTable
WHERE CustomerID = (SELECT CustomerID FROM CTE WHERE DUPS > 1)
AND BookLoan = (SELECT BookLoan FROM CTE WHERE DUPS > 1)
AND BookNumber = (SELECT BookNumber FROM CTE WHERE DUPS > 1)
AND BookAuthor = (SELECT BookAuthor FROM CTE WHERE DUPS > 1)
SELECT * FROM #tempTable

SQL: Remove duplicates

How do I remove duplicates from a table that is set up in the following way?
unique_ID | worker_ID | date | type_ID
A worker can have multiple type_ID's associated with them and I want to remove any duplicate types. If there is a duplicate, I want to remove the type with the most recent entry.
A textbook candidate for the window function row_number():
;WITH x AS (
SELECT unique_ID
,row_number() OVER (PARTITION BY worker_ID,type_ID ORDER BY date) AS rn
FROM tbl
)
DELETE FROM tbl
FROM x
WHERE tbl.unique_ID = x.unique_ID
AND x.rn > 1
This also takes care of the situation where a set of dupes on (worker_ID,type_ID) shares the same date.
See the simplified demo on data.SE.
Update with simpler version
Turns out, this can be simplified: In SQL Server you can delete from the CTE directly:
;WITH x AS (
SELECT unique_ID
,row_number() OVER (PARTITION BY worker_ID,type_ID ORDER BY date) AS rn
FROM tbl
)
DELETE x
WHERE rn > 1
delete from table t
where exists ( select 1 from table t2
where t2.worker_id = t.worker_id
and t2.type_id = t.type_id
and t2.date < t.date )
HTH
DELETE FROM #t WHERE unique_Id IN
(
SELECT unique_Id FROM
(
SELECT unique_Id
,Type_Id
,ROW_NUMBER() OVER (PARTITION BY worker_Id, type_Id ORDER BY date) AS rn
FROM #t
) Q
WHERE rn > 1
)
And to test...
DECLARE #t TABLE
(
unique_ID INT IDENTITY,
worker_ID INT,
date DATETIME,
type_ID INT
)
INSERT INTO #t VALUES (1, DATEADD(DAY, 1, GETDATE()), 1)
INSERT INTO #t VALUES (1, GETDATE(), 1)
INSERT INTO #t VALUES (2, GETDATE(), 1)
INSERT INTO #t VALUES (1, DATEADD(DAY, 2, GETDATE()), 1)
INSERT INTO #t VALUES (1, DATEADD(DAY, 3, GETDATE()), 2)
SELECT * FROM #t
DELETE FROM #t WHERE unique_Id IN
(
SELECT unique_Id FROM
(
SELECT unique_Id
,Type_Id
,ROW_NUMBER() OVER (PARTITION BY worker_Id, type_Id ORDER BY date) AS rn
FROM #t
) Q
WHERE rn > 1
)
SELECT * FROM #t
you may use this query
delete from worker where unique_id in (
select max(unique_id) from worker group by worker_ID , type_ID having count(type_id)>1)
here i am assuming worker as your table name

SQL Query using distinct and max

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