Reputation: 453
I have one table (say , table name is "items") as given below.
id | timestamp | name | amount |
---|---|---|---|
100 | 16106800 | pqr | 10 |
100 | 16106800 | pqr | 0 |
100 | 16106400 | pqr | 15 |
If there are more than one record with same name and same timestamp then I want to exclude one with zero amount. For example - In the above table , we have two records (first and second records) with same name and same timestamp, so I have to exclude one record with zero amount.
Expected result is as below:
id | timestamp | name | amount |
---|---|---|---|
100 | 16106800 | pqr | 10 |
100 | 16106400 | pqr | 15 |
I wrote a query like below but that doesn't work completely.
SELECT *
FROM items w
WHERE EXISTS (
SELECT *
FROM items x
WHERE x.timestamp = w.timestamp AND x.name=w.name
) AND w.amount > 0
My above query getting failed when all the timestamps are different. If there is no records with same name and same timestamp then it will not exclude anything from items table.
EDIT : If there is only one row with zero amount in that table then it should not be excluded.
Upvotes: 0
Views: 388
Reputation: 15389
My query produces these results:
If you have only one record despite the amount, it is showed
If you have more than one record, it will show only the records with amount > 0
So, try this:
SELECT *
FROM items t1
WHERE NOT EXISTS
(SELECT 1 FROM items t2
WHERE t1.id = t2.id
AND t1.timestamp = t2.timestamp
AND t1.name = t2.name
AND t2.amount > 0)
OR t1.amount > 0
See SQL Fiddle
Be aware: I've written on SQL Fiddle with a different DBMS but the SQL used is standard, so it's OK for SQL Server too.
Upvotes: 0
Reputation: 1270693
Why not just aggregate?
select id, timestamp, name, sum(amount) as amount
from items
group by id, timestamp, name;
This returns one row per id
/timestamp
/name
combination, with the total amount for that combination. I suspect this does what you really want.
But, you can also modify your query by tweaking the logic:
SELECT i.*
FROM items i
WHERE i.amount > 0 OR
NOT EXISTS (SELECT 1
FROM items i2
WHERE i2.timestamp = i.timestamp AND
i2.name = i.name AND
i2.amount > 0
);
That is, return all rows where the amount > 0
. And then also return all rows for a timestamp
/name
combination where there is no row with an amount > 0
.
Upvotes: 1
Reputation: 72153
A conditional Window Aggregate COUNT(CASE...) OVER...
is probably your best bet:
SELECT id, timestamp, name, amount
FROM (
SELECT *,
count(case when amount > 0 then 1 end)
over(partition by timestamp, name) CountNonZeroes
FROM Table
) t
WHERE CountNonZeroes = 0 OR amount > 0
Upvotes: 0
Reputation: 22811
Alternatively you can use count() over()
SELECT id, timestamp, name, amount
FROM (
SELECT *, count(*) over(partition by id, timestamp, name) cnt
FROM yourtable) t
WHERE cnt = 1 OR amount > 0
Upvotes: 0
Reputation: 1494
;with a as (
select distinct id,timestamp,name from items
),
with b as (
select * from items
where amount > 0
)
select a.id,a.timestamp,a.name,isnull(b.amount,0) amount
from a join b on a.timestamp = b.timestamp and a.name = b.name
Upvotes: 0