我有一个包含三列的表:
GEOID,ParcelID和PurchaseDate。
PK是GEOID和ParcelID,格式如下:
GEOID PARCELID PURCHASEDATE
12345 AB123 1/2/1932
12345 sfw123 2/5/2012
12345 fdf323 4/2/2015
12346 dfefej 2/31/2022 <-New GEOID
我需要的是基于GEOID的聚合。 我需要计算上个月PER GEOID的ParcelID数量 我需要提供上个月所有销售总额的GEOID百分比。
我需要制作三列: GEOID Nbr_Parcels_Sold Percent_of_total
对于每个GEOID,我需要知道上个月售出的包裹数量,并且根据该数量,找出所有销售所需的百分比。
例如:如果上个月有20个包裹被售出,其中4个从GEOID 12345出售,那么输出将是:
GEOID Nbr_Parcels_Sold Perc_Total
12345 4 .2 (or 20%)
我遇到双重聚合问题。令人担忧的是,该表有超过800万条记录。
如果此前有一位SQL Warrior曾经见过这个问题,那么任何智慧都会受到高度赞赏。 感谢。
答案 0 :(得分:2)
希望您使用的是SQL Server 2005或更高版本,在这种情况下,您可以利用windowed聚合。在这种情况下,窗口聚合将允许您获得总销售数和每GEOID
的计数,并在计算中使用总计。基本上,以下查询只返回计数:
SELECT
GEOID,
Nbr_Parcels_Sold = COUNT(*),
Total_Parcels_Sold = SUM(COUNT(*)) OVER ()
FROM
dbo.atable
GROUP BY
GEOID
;
COUNT(*)
调用根据GROUP BY子句为每个GEOID
提供计数。现在,SUM(...) OVER
表达式为您提供与详细计数在同一行中的总计数。它是空的OVER子句,它告诉SUM函数在整个结果集中添加COUNT(*)
的结果。您可以在计算中使用该结果,就像任何其他函数(或一般的任何表达式)的结果一样。
上述查询只返回总值。由于您实际上不需要值本身,而是每个GEOID
的百分比,您可以将SUM(...) OVER
调用放入表达式中:
SELECT
GEOID,
Nbr_Parcels_Sold = COUNT(*),
Percent_of_total = COUNT(*) * 100 / SUM(COUNT(*)) OVER ()
FROM
dbo.atable
GROUP BY
GEOID
;
以上将给出整数百分比(截断)。如果您想要更高的精度或不同的表示,请记住将除数或被除数(可选两者)转换为非整数数字类型,因为当两个操作数都是整数时,SQL Server始终执行积分除法。
答案 1 :(得分:1)
如何使用子查询来计算总和
WITH data AS
(
SELECT *
FROM [Table]
WHERE
YEAR(PURCHASEDATE) * 100 + MONTH(PURCHASEDATE) = 201505
)
SELECT
GEOID,
COUNT(*) AS Nbr_Parcels_Sold,
CONVERT(decimal(18,8), COUNT(*)) /
(SELECT COUNT(*) FROM data) AS Perc_Total
FROM
data t
GROUP BY
GEOID
修改强>
要按结果更新其他表格,请使用UPDATE
WITH()
WITH data AS
(
SELECT *
FROM [Table]
WHERE
YEAR(PURCHASEDATE) * 100 + MONTH(PURCHASEDATE) = 201505
)
UPDATE target SET
Nbr_Parcels_Sold = source.Nbr_Parcels_Sold,
Perc_Total = source.Perc_Total
FROM
[AnotherTable] target
INNER JOIN
(
SELECT
GEOID,
COUNT(*) AS Nbr_Parcels_Sold,
CONVERT(decimal(18,8), COUNT(*)) /
(SELECT COUNT(*) FROM data) AS Perc_Total
FROM
data t
GROUP BY
GEOID
) source ON target.GEOID = source.GEOID
答案 2 :(得分:0)
尝试以下方法。它将总销售额计入变量,然后在后续查询中使用它:
DECLARE @pMonthStartDate DATETIME
DECLARE @MonthEndDate DATETIME
DECLARE @TotalPurchaseCount INT
SET @pMonthStartDate = <EnterFirstDayOfAMonth>
SET @MonthEndDate = DATEADD(MONTH, 1, @pMonthStartDate)
SELECT
@TotalPurchaseCount = COUNT(*)
FROM
GEOIDs
WHERE
PurchaseDate BETWEEN @pMonthStartDate
AND @MonthEndDate
SELECT
GEOID,
COUNT(PARCELID) AS Nbr_Parcels_Sold,
CAST(COUNT(PARCELID) AS FLOAT) / CAST(@TotalPurchaseCount AS FLOAT) * 100.0 AS Perc_Total
FROM
GEOIDs
WHERE
ModifiedDate BETWEEN @pMonthStartDate
AND @MonthEndDate
GROUP BY
GEOID
我猜你的表名是GEOIDs。更改@pMonthStartDate的值以适合自己。如果您的PK如您所说那么这将是一个快速查询。