使用子查询更新表

时间:2019-01-06 14:43:04

标签: sql sql-server

我有一个Foo表,具有以下属性:

FooID (PK) | Bar | Price

鉴于示例记录集为:

1 | 332 | 10
2 | 332 | 10
3 | 333 | 5
4 | 334 | 30
4 | 334 | 30
4 | 334 | 30

我希望查询的输出为

1 | 332 | 5
2 | 332 | 5
3 | 333 | 5
4 | 334 | 10
4 | 334 | 10
4 | 334 | 10

换句话说,Price列应该是以下内容的结果:Price/N,其中N是给定Bar在记录集中存在的次数。

我设法使用以下方法来计算存在的Bars的数量:

  select Bar, count(*) as BarCount from Foo GROUP BY Bar

但是,我不知道如何将其应用于Price的划分。

谢谢!

3 个答案:

答案 0 :(得分:4)

您可以使用窗口功能和除法:

select fooid, bar, 
       price / count(*) over (partition by bar) as new_price
from t;

Demo

请注意,SQL Server执行整数除法。因此,如果price是整数,则可能会得到更准确的结果:

select fooid, bar, 
       price * 1.0 / count(*) over (partition by bar) as new_price
from t;

编辑:

标题为“更新”,但问题仅提及获得结果。如果要更新,请使用可更新的CTE或子查询:

with toupdate as (
      select t.*, 
             price / count(*) over (partition by bar) as new_price
      from t
     )
update toupdate
    set new_price = price
    where price <> new_price;

答案 1 :(得分:2)

您可以使用CTE查找每个Bar组的计数,然后加入该组以查找商:

WITH cte AS (
    SELECT Bar, COUNT(*) AS cnt
    FROM yourTable
    GROUP BY Bar
)

SELECT t1.FooID, t1.Bar,
   1.0 * t1.Price / t2.cnt AS NewPrice
FROM yourTable t1
INNER JOIN cte t2
    ON t1.Bar = t2.Bar
ORDER BY
    t1.Bar, t1.FooID;

enter image description here

Demo

戈登的答案可能是最快的,因为它可以找到计数并在整个表格中一次计算商数。我给出的答案需要一个额外的子查询并加入。

答案 2 :(得分:1)

使用相关子查询来计算除法器:

WITH myTable AS (
    SELECT 1 AS FooID, 332 AS Bar, 10 AS Price UNION ALL
    SELECT 2, 332, 10 UNION ALL
    SELECT 3, 333, 5  UNION ALL
    SELECT 4, 334, 30 UNION ALL
    SELECT 4, 334, 30 UNION ALL
    SELECT 4, 334, 30
)    
SELECT 
    t.fooid,
    t.bar,
    t.price / (SELECT COUNT(*) FROM myTable WHERE bar = t.bar)
FROM myTable t
GO
fooid | bar | (No column name)
----: | --: | ---------------:
    1 | 332 |                5
    2 | 332 |                5
    3 | 333 |                5
    4 | 334 |               10
    4 | 334 |               10
    4 | 334 |               10

db <>提琴here