根据某些列过滤 table 中的记录

Filter records in a table based on some columns

我有一个 table(比如说,table 名称是“items”),如下所示。

id timestamp name amount
100 16106800 pqr 10
100 16106800 pqr 0
100 16106400 pqr 15

如果有多个记录具有相同的名称和相同的时间戳,那么我想排除一个数量为零的记录。例如 - 在上面的 table 中,我们有两条记录(第一条和第二条记录)具有相同的名称和相同的时间戳,所以我必须排除一条金额为零的记录。

预期结果如下:

id timestamp name amount
100 16106800 pqr 10
100 16106400 pqr 15

我写了一个如下的查询,但它并不完全有效。

SELECT *
FROM items w
WHERE EXISTS (
    SELECT *
    FROM items x  
    WHERE x.timestamp = w.timestamp AND x.name=w.name
) AND w.amount > 0

当所有时间戳都不同时,我的上述查询失败。如果没有具有相同名称和相同时间戳的记录,那么它不会从项目 table.

中排除任何内容

EDIT :如果 table 中只有一行的金额为零,则不应将其排除在外。

我的查询产生了这些结果:

如果您只有一条记录,不管金额多少,都会显示

如果您有多条记录,它只会显示金额> 0的记录

所以,试试这个:

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

SQL Fiddle

请注意:我已经用不同的 DBMS 在 SQL Fiddle 上写过,但使用的 SQL 是标准的,因此 SQL 服务器也可以。

或者您可以使用 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

db<>Fiddle

;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

条件 Window 聚合 COUNT(CASE...) OVER... 可能是您最好的选择:

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

为什么不聚合?

select id, timestamp, name, sum(amount) as amount
from items
group by id, timestamp, name;

此 return 每个 id/timestamp/name 组合一行,以及该组合的总金额。我怀疑这确实是您真正想要的。

但是,您也可以通过调整逻辑来修改查询:

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
                 );

即 return amount > 0 所在的所有行。然后 return timestamp/name 组合的所有行,其中没有包含 amount > 0.

的行