SQL如何不基于行计算中值
我的表中有一个汽车样本,我想用SQL计算样本的中间价。最好的方法是什么SQL如何不基于行计算中值,sql,sql-server,median,Sql,Sql Server,Median,我的表中有一个汽车样本,我想用SQL计算样本的中间价。最好的方法是什么 +-----+-------+----------+ | Car | Price | Quantity | +-----+-------+----------+ | A | 100 | 2 | | B | 150 | 4 | | C | 200 | 8 | +-----+-------+----------+ 我知道如果我的表格如下所示,我可以使用perce
+-----+-------+----------+
| Car | Price | Quantity |
+-----+-------+----------+
| A | 100 | 2 |
| B | 150 | 4 |
| C | 200 | 8 |
+-----+-------+----------+
我知道如果我的表格如下所示,我可以使用percentile_cont或percentile_disc:
+-----+-------+
| Car | Price |
+-----+-------+
| A | 100 |
| A | 100 |
| B | 150 |
| B | 150 |
| B | 150 |
| B | 150 |
| C | 200 |
| C | 200 |
| C | 200 |
| C | 200 |
| C | 200 |
| C | 200 |
| C | 200 |
| C | 200 |
+-----+-------+
但在现实世界中,我的第一张桌子有大约1亿行,第二张桌子应该有大约3行台球,而且我不知道如何将我的第一张桌子转换成第二张桌子。这在一些结果上看起来是正确的,但试着用一个更大的集合进行双重检查 首先创建一个表,其中包含每辆车的总数,或者使用CTE或子查询(由您选择)。我只是在这里创建一个单独的表
create table table2 as
(
select car,
quantity,
price,
price * quantity as total
from table1
)
然后运行此查询,查找属于中间的价格组。
select price
from (
select car, price,
sum(total) over (order by car) as rollsum,
sum(total) over () as total
from table2
)a
where rollsum >= total/2
正确返回$200的值。这在少数结果中看起来是正确的,但请尝试在更大的集合中进行双重检查 首先创建一个表,其中包含每辆车的总数,或者使用CTE或子查询(由您选择)。我只是在这里创建一个单独的表
create table table2 as
(
select car,
quantity,
price,
price * quantity as total
from table1
)
然后运行此查询,查找属于中间的价格组。
select price
from (
select car, price,
sum(total) over (order by car) as rollsum,
sum(total) over () as total
from table2
)a
where rollsum >= total/2
正确返回$200的值。以下是在sql server中执行此操作的一种方法 在第一步中,我要做的是计算与中位数的上下限相对应的索引,如果我们有奇数个元素,那么上下限是相同的,否则它基于x/2和x/2+1的值 然后我得到数量的累积和,并使用它来选择对应于上下限的元素,如下所示
with median_dt
as (
select case when sum(quantity)%2=0 then
sum(quantity)/2
else
sum(quantity)/2 + 1
end as lower_limit
,case when sum(quantity)%2=0 then
(sum(quantity)/2) + 1
else
sum(quantity)/2 + 1
end as upper_limit
from t
)
,data
as (
select *,sum(quantity) over(order by price asc) as cum_sum
from t
)
,rnk_val
as(select *
from (
select price,row_number() over(order by d.cum_sum asc) as rnk
from data d
join median_dt b
on b.lower_limit<=d.cum_sum
)x
where x.rnk=1
union all
select *
from (
select price,row_number() over(order by d.cum_sum asc) as rnk
from data d
join median_dt b
on b.upper_limit<=d.cum_sum
)x
where x.rnk=1
)
select avg(price) as median
from rnk_val
+--------+
| median |
+--------+
| 200 |
+--------+
小提琴链接
以下是在sql server中执行此操作的一种方法 在第一步中,我要做的是计算与中位数的上下限相对应的索引,如果我们有奇数个元素,那么上下限是相同的,否则它基于x/2和x/2+1的值 然后我得到数量的累积和,并使用它来选择对应于上下限的元素,如下所示
with median_dt
as (
select case when sum(quantity)%2=0 then
sum(quantity)/2
else
sum(quantity)/2 + 1
end as lower_limit
,case when sum(quantity)%2=0 then
(sum(quantity)/2) + 1
else
sum(quantity)/2 + 1
end as upper_limit
from t
)
,data
as (
select *,sum(quantity) over(order by price asc) as cum_sum
from t
)
,rnk_val
as(select *
from (
select price,row_number() over(order by d.cum_sum asc) as rnk
from data d
join median_dt b
on b.lower_limit<=d.cum_sum
)x
where x.rnk=1
union all
select *
from (
select price,row_number() over(order by d.cum_sum asc) as rnk
from data d
join median_dt b
on b.upper_limit<=d.cum_sum
)x
where x.rnk=1
)
select avg(price) as median
from rnk_val
+--------+
| median |
+--------+
| 200 |
+--------+
小提琴链接
您试过这个吗?所有方法都适用于我的第二个表,而不是第一个表。这将是平均价格,而不是中间价。请标记您使用的数据库George Joseph,我有两个数据库-Oracle和SQL Server。您尝试过这个吗?所有方法都适用于我的第二个表,而不是第一个Jarlh,这将是平均价格而不是中间价请标记您使用的数据库George Joseph,我有两个DB-Oracle和SQL服务器,我认为如果相同的值有一半以上的行数,这将不起作用……我在额外的步骤中使用了相同的方法,我选择了最接近50%的价格组。但我想使用percintle_CONT中的线性插值,我希望它在我的样本中只有一个点时起作用。我认为如果同一个值的行数超过一半,这将不起作用……我在额外步骤中使用了相同的方法,我选择了最接近50%的价格组。但是我想使用线性插值,就像percintle_CONT一样,我希望它在我的样本中只有一个点时工作。