SQL按前3位和其他位置对行进行分组。(按州排名前三的城市和其他城市分列的收入)
所以我有一个查询,它给出了我的每个城市,它的对应状态,以及我的客户在该城市的消费价值 我想用每个城市的总客户价值来定义前三名 查询比这复杂一点,但这是它的核心:SQL按前3位和其他位置对行进行分组。(按州排名前三的城市和其他城市分列的收入),sql,sql-server,window-functions,Sql,Sql Server,Window Functions,所以我有一个查询,它给出了我的每个城市,它的对应状态,以及我的客户在该城市的消费价值 我想用每个城市的总客户价值来定义前三名 查询比这复杂一点,但这是它的核心: SELECT DISTINCT --* LTRIM(RTRIM(cs.City)) City ,LTRIM(RTRIM(cs.State)) State ,SUM(cs.TotalCustomerValueOverBase) over (partition by cs.City, cs.Sta
SELECT DISTINCT
--*
LTRIM(RTRIM(cs.City)) City
,LTRIM(RTRIM(cs.State)) State
,SUM(cs.TotalCustomerValueOverBase) over (partition by cs.City, cs.State) TotalCustomerValue
,SUM(cs.TotalOrdersBase) over (partition by cs.City, cs.State) TotalOrders
FROM ( -- This table gives full customer information per customer.
)CSS
我想做的是创建一个表,其中有每个州的前3个城市,然后是另一行,它将被视为所有其他城市的总和。所以整个表有200行,50*4
我正试着用行号做一些事情,但我似乎做不到
,ROW_NUMBER() over (partition by cs.City, cs.State Order by sum(CS.TotalCustomerValueOverBase)) rowNr
然后我可以尝试将所有大于3的行号相加
有人有什么想法吗
然后我假设SSR当我想用这些数据创建视觉效果时,我可以像过滤器一样在所有行上创建关键字Other,对吗
下面是我的完整查询,试图实现Gordon的解决方案
SELECT
(case when CSS.seqnum <= 3 then city else 'Others' end) as city,
(case when seqnum <= 3 then state end) as state
sum(TotalCustomerValue) as TotalCustomerValue,
sum(TotalOrders) as TotalOrders
FROM
(
SELECT DISTINCT
--*
LTRIM(RTRIM(cs.City)) City
,LTRIM(RTRIM(cs.State)) State
,right(left(lat, len(lat) -1),len(lat) -2) lat -- the lat and long are wrapped in quotes
,right(left(lng, len(lng) -1),len(lng) -2) lng -- so i have to do the left right to get rid of them.
,SUM(cs.TotalCustomerValueOverBase) over (partition by cs.City, cs.State) TotalCustomerValue
,SUM(cs.TotalOrdersBase) over (partition by cs.City, cs.State) TotalOrders
--,SUM(cs.TotalQuantityOverBase) over (partition by cs.City, cs.State) TotalQuantity
,CONVERT(float, right(left(population_proper, len(population_proper) -1),len(population_proper) -2)) population_proper
,CAST(
SUM(cs.TotalOrdersBase) over (partition by cs.City, cs.State)
/
NULLIF(convert(float, right(left(population_proper, len(population_proper) -1),len(population_proper) -2)),0)--*100
as decimal(10,4)) AS OrderDensityPercent
,SUM(cs.BrandNewCustomer) over (partition by cs.City, cs.State) BrandNewCustomers
,SUM(cs.RecurringCustomer) over (partition by cs.City, cs.State) RecurringCustomers
,SUM(cs.ReactivatedCustomer) over (partition by cs.City, cs.State) ReactivatedCustomers
,row_number() over (partition by ltrim(rtrim(cs.State)) order by sum(cs.TotalCustomerValueOverBase) desc) as seqnum
FROM ( -- This table gives full customer information per customer.
SELECT
CC.CustomerEmail
,CC.Month Month
,CONCAT(CC.Year, '-', CASE WHEN CC.Month < 10 then '0' else '' end, CC.Month) Date
,CASE WHEN
( ISNULL(CC.TotalOrdersCustomerBase,0) >= 1
AND ISNULL(RC.TotalOrdersRecurringBase,0) = 0
AND ISNULL(LC.TotalOrdersLifetimeBase,0) = 0)
THEN 1 ELSE 0 END BrandNewCustomer
,CASE WHEN
( ISNULL(CC.TotalOrdersCustomerBase,0) >= 1
AND ISNULL(RC.TotalOrdersRecurringBase,0) >= 1)
THEN 1 ELSE 0 END RecurringCustomer
,CASE WHEN
( ISNULL(CC.TotalOrdersCustomerBase,0) >= 1
AND ISNULL(RC.TotalOrdersRecurringBase,0) = 0
AND ISNULL(LC.TotalOrdersLifetimeBase,0) >= 1)
THEN 1 ELSE 0 END ReactivatedCustomer
,ISNULL(CC.TotalCustomerValueOverCustomerBase,0) TotalCustomerValueOverCustomerBase
,ISNULL(CC.TotalOrdersCustomerBase,0) TotalOrdersCustomerBase
,ISNULL(CC.TotalQuantityOverCustomerBase,0) TotalQuantityOverCustomerBase
,ISNULL(RC.TotalCustomerValueOverRecurringBase,0) TotalCustomerValueOverRecurringBase
,ISNULL(RC.TotalOrdersRecurringBase,0) TotalOrdersRecurringBase
,ISNULL(RC.TotalQuantityOverRecurringBase,0) TotalQuantityOverRecurringBase
,ISNULL(LC.TotalCustomerValueOverLifetimeBase,0) TotalCustomerValueOverLifetimeBase
,ISNULL(LC.TotalOrdersLifetimeBase,0) TotalOrdersLifetimeBase
,ISNULL(LC.TotalQuantityOverLifetimeBase,0) TotalQuantityOverLifetimeBase
,ISNULL(FC.TotalCustomerValueOverBase,0) TotalCustomerValueOverBase
,ISNULL(FC.TotalOrdersBase,0) TotalOrdersBase
,ISNULL(FC.TotalQuantityOverBase,0) TotalQuantityOverBase
,ISNULL(CC.TotalCustomersOverCustomerBase,0) TotalCustomersOverCustomerBase
,ISNULL(RC.TotalCustomersOverRecurringBase,0) TotalCustomersOverRecurringBase
,ISNULL(LC.TotalCustomersOverLifetimeBase,0) TotalCustomersOverLifetimeBase
,ISNULL(FC.TotalCustomersOverBase,0) TotalCustomersOverBase
,CC.City
,CC.State
,CC.CountryCode
From
(
SELECT
C.CustomerEmail
,C.Month
,C.Year
,C.TotalCustomersOverCustomerBase
,C.TotalCustomerValueOverCustomerBase
,C.TotalOrdersCustomerBase
,C.TotalQuantityOverCustomerBase
,C.City
,C.State
,C.CountryCode
FROM
#CustomerBase C
WHERE C.OrderCountCustomerBase = 1 -- This makes it return only the first row of a customer with multiple purchases.
--and TotalOrdersCustomerBase = TotalQuantityOverCustomerBase
) CC
LEFT JOIN
(
SELECT
R.CustomerEmail
,R.TotalCustomersOverRecurringBase
,R.TotalCustomerValueOverRecurringBase
,R.TotalOrdersRecurringBase
,R.TotalQuantityOverRecurringBase
FROM
#RecurringBase R
WHERE R.OrderCountRecurringBase = 1
) RC ON CC.CustomerEmail = RC.CustomerEmail
LEFT JOIN
(
SELECT
L.CustomerEmail
,L.TotalCustomersOverLifetimeBase
,L.TotalCustomerValueOverLifetimeBase
,L.TotalOrdersLifetimeBase
,L.TotalQuantityOverLifetimeBase
FROM
#LifetimeBase L
WHERE L.OrderCountLifetimeBase = 1
) LC ON CC.CustomerEmail = LC.CustomerEmail
LEFT JOIN
(
SELECT
F.CustomerEmail
,F.TotalCustomersOverBase
,F.TotalCustomerValueOverBase
,F.TotalOrdersBase
,F.TotalQuantityOverBase
FROM
#FullBase F
WHERE F.OrderCountBase = 1
) FC ON CC.CustomerEmail = FC.CustomerEmail
) Cs --Customers
LEFT JOIN [A1Warehouse].[dbo].[uscities] Ci ON cs.City = right(left(ci.city_ascii, len(ci.city_ascii) -1),len(ci.city_ascii) -2) and cs.State = right(left(ci.state_id, len(ci.state_id) -1),len(ci.state_id) -2)
WHERE
LAT IS NOT NULL
AND LNG IS NOT NULL
group by ltrim(rtrim(cs.City)), ltrim(rtrim(cs.State))
)CSS
Where CAST(CSS.LAT AS FLOAT) > 20 AND CAST(CSS.LNG AS FLOAT) > -120
group by (case when seqnum <= 3 then city else 'Others' end),
(case when seqnum <= 3 then state end)
ORDER BY TotalCustomerValue DESC
您可以使用两个级别的聚合和一些条件逻辑:
select (case when seqnum <= 3 then city else 'Others' end) as city,
state,
sum(TotalCustomerValue) as TotalCustomerValue,
sum(TotalOrders) as TotalOrders
from (select ltrim(rtrim(cs.City)) as City, ltrim(rtrim(cs.State)) as State,
sum(cs.TotalCustomerValueOverBase) as TotalCustomerValue,
sum(cs.TotalOrdersBase) as TotalOrders,
row_number() over (partition by ltrim(rtrim(cs.State)) order by sum(cs.TotalCustomerValueOverBase) desc) as seqnum
from . . . cs
group by ltrim(rtrim(cs.City)), ltrim(rtrim(cs.State))
) cs
group by (case when seqnum <= 3 then city else 'Others' end),
(case when seqnum <= 3 then state end)
编辑:
根据评论,您可以执行以下操作:
select (case when seqnum <= 3 then city else 'Others' end) as city,
(case when seqnum <= 3 then state end) as state,
sum(TotalCustomerValue) as TotalCustomerValue,
sum(TotalOrders) as TotalOrders
from (select ltrim(rtrim(cs.City)) as City, ltrim(rtrim(cs.State)) as State,
sum(cs.TotalCustomerValueOverBase) as TotalCustomerValue,
sum(cs.TotalOrdersBase) as TotalOrders,
row_number() over (partition by ltrim(rtrim(cs.State)) order by sum(cs.TotalCustomerValueOverBase) desc) as seqnum
from . . . cs
group by ltrim(rtrim(cs.City)), ltrim(rtrim(cs.State))
) cs
group by (case when seqnum <= 3 then city else 'Others' end),
state
您如何定义前三名?我已经添加了这些信息,由TotalCustomerValueGordon提供,我已经尝试实施您的解决方案,但我似乎无法让它发挥作用。我已经编辑了我的原始问题,以包含完整的查询和我试图集成代码的尝试。我做错什么了吗?问题似乎出在group by上,我无法解决。我让查询工作,但它将所有其他作为一个大桶,我试图在每个州做一个其他桶。那可能吗@纳坦。你只需要通过调整组就可以了。