【问题标题】:SQL Group by and update/delete rowSQL Group by 和更新/删除行
【发布时间】:2018-01-30 07:38:33
【问题描述】:

我有一个 SQL.Table

CREATE TABLE [dbo].[Stack_Example](
    [ID] [bigint] NOT NULL,
    [Product_ID] [bigint] NULL,
    [Quantity] [decimal](18, 2) NULL,
    [Price] [decimal](18, 2) NULL,
 CONSTRAINT [PK_Stack_Example] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

数据如下所示:

INSERT [dbo].[Stack_Example] ([ID], [Product_ID], [Quantity], [Price]) VALUES (1, 25, CAST(55.00 AS Decimal(18, 2)), CAST(1000.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[Stack_Example] ([ID], [Product_ID], [Quantity], [Price]) VALUES (2, 25, CAST(1.00 AS Decimal(18, 2)), CAST(1000.00 AS Decimal(18, 2)))
GO
INSERT [dbo].[Stack_Example] ([ID], [Product_ID], [Quantity], [Price]) VALUES (3, 26, CAST(1.00 AS Decimal(18, 2)), CAST(500.00 AS Decimal(18, 2)))
GO

所以我的问题是我需要按价格、产品 ID 和总和(数量)对这些项目进行分组。

假设我的输出窗口需要看起来像这样,则需要更新/删除查询

选择查询很简单

select Product_ID,SUM(Quantity) AS Quantity,Price from Stack_Example
Group by Product_ID,Price

所以一开始我需要做的是删除 id 为 2 的行并更新 id 为 1 的行 set Quantity = Quantity + 1 ( Quantity of deleted row )。

所以当我运行选择查询而不分组和求和时,我需要得到相同的输出

UPDATE Stack_Example SET Quantity = (SELECT SUM(Quantity)
                                    FROM Stack_Example child 
                                    WHERE child.Product_ID = Stack_Example.Product_ID
                                    GROUP BY Product_ID)

DELETE FROM Stack_Example WHERE ID IN (SELECT TOP 1 ID 
                                        FROM Stack_Example 
                                        WHERE Product_Id IN ( (SELECT TOP 1 Product_ID 
                                                                    FROM Stack_Example
                                                                    GROUP BY Product_ID 
                                                                    HAVING COUNT(Product_ID)>1)))

【问题讨论】:

  • 对不起,我无法清楚地了解您真正想要什么。

标签: sql sql-server


【解决方案1】:

首先用相同价格的产品总量更新您的表格

with cte as (
    select
        Product_ID, Price, Quantity = sum(Quantity) 
    from
        Stack_Example
    group by Product_ID, Price
)

update s
set s.Quantity = c.Quantity
from
    Stack_Example s
    join cte c on s.Product_ID = c.Product_ID and s.Price = c.Price

然后运行另一个脚本来删除重复的行

with cte as (
    select
        *, row_number() over (partition by Product_ID, Price order by Product_ID) rn
    from
        Stack_Example
)

delete from cte where rn > 1

【讨论】:

    【解决方案2】:

    我有点不清楚 - 但你不能只用聚合创建一个视图吗?

    无论如何...... 不知道你为什么要这样做,但是......你可以插入聚合值,然后删除旧的......如下所示。

    DECLARE @MaxId INT;
    DECLARE @ProductId = 25;
    
    
    --GET THE MAX ID OF PRODUCT IN QUESTION
    SELECT @MaxId = MAX(ID) FROM Stack_Example WHERE Product_Id = @ProductId;
    
    
    --INSERT THE AGGREGATE VALUES INTO TABLE
    INSERT INTO Stack_Example
      SELECT @MaxId + 1, @ProductId, Price, SUM(Quantity)
      FROM Stack_Example
      WHERE 
        Product_Id = @ProductId
      GROUP BY 
        @MaxId + 1, [Product_ID], [Price];
    
    --DELETE THE PRE-AGGREGATE VALUES
    DELETE FROM Stack_Example WHERE ProductId = @ProductId and Id <= @MaxId;
    

    【讨论】:

    • 感谢您的快速答复。如果您查看我提出的作为答案的代码,它可能会帮助您理解我。我的代码中的主要问题是它仅在每个相同项目有 2 行时才有效。如果我添加具有相同 Product_Id 的三行,它不会让我删除,因为我得到 TOP 1
    • 为什么不直接使用视图?
    【解决方案3】:

    嗯,我使用了聚合和额外的临时表来实现这一点:

    --group records and insert them into temporary table
    select distinct
         Min(id) over (partition by product_id, price) [ID],
         Product_id,
         sum(Quantity) over (partition by product_id, price) [Quantity],
         Price
    into #new_stack_example
    from #Stack_Example
    
    --delete old values
    delete #Stack_example
    
    --insert new values
    insert into #Stack_example
    select * from #new_stack_example
    

    第一个SELECT 语句反映了您的逻辑:

    所以我的问题是我需要按价格、产品 ID 和总和(数量)对这些项目进行分组。

    但我没有分组,而是使用窗口函数,然后选择不同的记录。

    【讨论】:

      【解决方案4】:

      检查这个:

          UPDATE Stack_Example SET Quantity = a.Quantity
          from ( select Product_ID,sum(Quantity) Quantity  
          from Stack_Example Group by Product_ID) a
          where   Stack_Example.Product_ID=a.Product_ID   
      
          ;with cte as (
          select *,ROW_NUMBER () over (partition by product_id order by product_id) rn 
          from Stack_Example)
      
          delete from cte where rn > 1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        • 1970-01-01
        • 2012-07-06
        • 2013-04-06
        相关资源
        最近更新 更多