【问题标题】:How to delete smaller records for each group?如何删除每个组的较小记录?
【发布时间】:2011-10-12 11:13:00
【问题描述】:

我的表 price 具有当前架构:

item date         shift     price1  price2
1    20110723     day       40      50
1    20110723     night     42      52
1    20110723     weekend   42      52
2    20110723     Night     40      50
...

并且我想为表中的每个项目保留最高价格 1 或价格 2 的记录,即从表中删除价格 1 或价格 2 较小的记录。 sql怎么写?

我使用 sybase ASE 12.5

【问题讨论】:

  • 主键是什么,如果有的话? (项目、日期、班次)?
  • 那么,如果item=7 有三行,price1,price2 = 30,100100,3040,40,哪些应该被删除?
  • @cularis:您可以假设项目、日期、班次为键。
  • @ypercube: 40,40 将被删除。

标签: sql select group-by max sql-delete


【解决方案1】:

在 SQL Server(可能还有其他一些 RDBMS)中,您可以使用 CTEranking,如下所示:

WITH ranked AS (
  SELECT
    *,
    price1rank = RANK() OVER (PARTITION BY item ORDER BY price1 DESC),
    price2rank = RANK() OVER (PARTITION BY item ORDER BY price2 DESC)
  FROM Test1
)
DELETE FROM ranked
WHERE price1rank <> 1
  AND price2rank <> 1;

更新

发布整个测试脚本,包括上面的 DELETE 语句,以便任何愿意使用它的人都可以使用它或只是验证它是否有效:

CREATE TABLE Test1 (
  item int,
  date date,
  shift varchar(30),
  price1 money,
  price2 money
);
GO
INSERT INTO Test1 (item, date, shift, price1, price2)
SELECT 1, '20110723', 'day    ', 40, 50 UNION ALL
SELECT 1, '20110723', 'night  ', 42, 52 UNION ALL
SELECT 1, '20110723', 'weekend', 42, 52 UNION ALL
SELECT 2, '20110723', 'Night  ', 40, 50;
GO
SELECT * FROM Test1
GO
WITH Test1Ranked AS (
  SELECT
    *,
    price1rank = RANK() OVER (PARTITION BY item ORDER BY price1 DESC),
    price2rank = RANK() OVER (PARTITION BY item ORDER BY price2 DESC)
  FROM Test1
)
DELETE FROM Test1Ranked
WHERE price1rank <> 1
  AND price2rank <> 1;
GO
SELECT * FROM Test1
GO
DROP TABLE Test1
GO

【讨论】:

    【解决方案2】:

    如果您在 oracle 中工作,您可以编写以下查询 -

    delete from item_table where rowid not in
    (
         select rowid from item_table 
         where (item,price1) in (select item,max(price1) from item_table group by item)
            or (item,price2) in (select item,max(price2) from item_table group by item)
    )
    

    听说 sql server 或 mysql 中没有 rowid ... 请告诉我们您使用的数据库名称。

    你也可以这样写..

    delete from item_table where (item,date,shift,price1,price2 ) not in
        (
            select item,date,shift,price1,price2  from item_table 
            where (item,price1) in (select item,max(price1) from item_table group by item)
               or (item,price2) in (select item,max(price2) from item_table group by item)
        )
    

    【讨论】:

    • 我使用 sybase ASE 12.5。我对 SQL 和 sybase 都不熟悉。 sybase是否支持rowid?如果数据集很大,输入/不输入会影响性能吗?
    • 如果你的数据库支持rowid,那么你最好使用rowid...它会提高你的性能
    • sybase中好像没有rowid。但是你的第二个 sql 有效。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2021-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 1970-01-01
    • 2011-03-30
    相关资源
    最近更新 更多