【问题标题】:Getting the median value from the database从数据库中获取中值
【发布时间】:2019-02-16 21:04:59
【问题描述】:

中位数定义为将数据集的上半部分与下半部分分开的数字。从 STATION 查询北纬 (LAT_N) 的中位数并将您的答案四舍五入到小数位。

输入格式

STATION表描述如下:

Field : Type
ID    : NUMBER
CITY  : VARCHAR2(21)
STATE : VARCHAR2(2)
LAT_N : NUMBER
LONG_W: NUMBER

其中 LAT_N 是北纬,LONG_W 是西经。

我只能设法获得中值的行索引

select floor((count(lat_n)+1)/2) from station;

即行索引250。下一步是使用该值提取行索引250处的lat_n值。如何转换为SQL?

【问题讨论】:

  • 哪个数据库系统?甲骨文?SQLS?后格雷斯? mysql?等
  • 欢迎来到 SO!几乎可以保证,以前有人问过这个问题,请进行搜索(如有必要,请使用 google 搜索此站点 - 它比 SO 的内置搜索更好)并告诉我们您尝试了什么
  • 根据numbervarchar2 数据类型的使用情况标记为oracle
  • 边缘情况:对于偶数表,中位数通常报告为中间两条记录的mean值。
  • 顺便说一句,看起来你已经从家庭作业或考试类型的练习中倾倒了文本,我默认不提交答案,因为我不认为使用 SO一个家庭作业完成设备,在您自己的学习方面合理利用时间。请看一下techonthenet.com/oracle/functions/median.php - oracle 有一个功能来做中位数,你的问题缺乏足够的细节让你以外的任何人(谁知道你想要的中位数)来完成..

标签: sql oracle select


【解决方案1】:

我们都知道元素个数为奇数时的中位数是多少,偶数是第(n+1)/2项,奇数是((n/2)项+(n/2)+1项)/2 所以使用这个代码。

set @r1=0,@r2=0,@r3=0,@r4=0;
select
case
when mod(count(cnt),2)=0 then 
                        ((select round(lat_n,4) from (select @r3:=@r3+1 as cnt2, lat_n from station order by lat_n) temp2 where cnt2=(@r3)/2)+(select round(lat_n,4) from (select @r4:=@r4+1 as cnt3, lat_n from station order by lat_n) temp3 where cnt3=(@r4+1)/2))/2
else (select round(lat_n,4) from (select @r2:=@r2+1 as cnt1, lat_n from station order by lat_n) temp1 where cnt1=(@r2+1)/2)
end
from (select @r1:=@r1+1 as cnt, lat_n from station ) temp;

【讨论】:

    【解决方案2】:

    MYSQL 代码:

    SELECT ROUND(lat_n,4)
    ---------------------
    FROM (
         SELECT lat_n,
         ROW_NUMBER() OVER(ORDER BY lat_n ) AS row_num
         FROM station
         )  AS new_table
    --------------------
    WHERE row_num = (
                    SELECT CEIL(AVG(row_num)) 
                    FROM (
                          SELECT 
                          ROW_NUMBER() OVER(ORDER BY lat_n ) AS row_num
                          FROM station
                          )  AS new_table
                     )
    -------------------
    

    【讨论】:

      【解决方案3】:

      这行得通 甲骨文:

      SELECT round(median(lat_n),4) from station;
      

      【讨论】:

      • 这是一个很好的答案,可以解决发帖人的主要观点,但我不确定是否需要四舍五入。也许只是select median(lat_n) from station;
      • 我猜答案与 HackerRanks 的挑战有关,要求将结果四舍五入到小数点 @catfood
      【解决方案4】:

      您可以使用 Oracle 运行以下代码。

      SELECT ROUND(MEDIAN(LAT_N), 4)
      FROM STATION;
      

      【讨论】:

        【解决方案5】:

        这个解决方案更通用。

        我们得到总长度,如果是奇数则加 1。

        然后我们排序,只得到中间项。

        SET @length := ( SELECT COUNT(*) FROM STATION);
        SET @offset :=  (IF(@length  % 2 <> 0 , @length+1 , @length)/2)-1 ;
        
        PREPARE STMT FROM 'SELECT ROUND(LAT_N,4) FROM STATION ORDER BY LAT_N LIMIT ? , 1';
        EXECUTE STMT USING @offset;
        

        【讨论】:

          【解决方案6】:

          对于 mySQL 这会起作用,

             SELECT ROUND(S1.LAT_N, 4) 
              FROM STATION AS S1 
              WHERE (SELECT ROUND(COUNT(S1.ID)/2) - 1 
                     FROM STATION) = 
                    (SELECT COUNT(S2.ID) 
                     FROM STATION AS S2 
                     WHERE S2.LAT_N > S1.LAT_N);
          

          参考:https://nikkesan.gitbook.io/hackerrank/practice-1/sql/aggregation/untitled-2

          【讨论】:

            【解决方案7】:

            SQL 服务器:

            DECLARE @slno int;
            SET @slno= (select COUNT(*) from STATION);
            with cte (ind,LAT_N)
            as
            ( select ROW_NUMBER() OVER(ORDER BY LAT_N ASC) AS ind, LAT_N from STATION
            )
            select 
            CAST(LAT_N AS DECIMAL(15,4))
            from cte
            where ind= (@slno+1)/2
            order by LAT_N
            

            【讨论】:

            • 请简要介绍您的答案 - 这是如何解决问题的。谢谢。
            • step1: In cte --add row number to each row and name the column as ind. step2:在变量 slno 中 - 添加总行数第 3 步:打印 Lat_N 其中第 1 步计算的索引位于中间,这样中间位置将是第 2 步计算的 slno+1/2。
            【解决方案8】:

            与 cte 作为 ( SELECT ROW_NUMBER()OVER(ORDER BY LAT_N)rw,LAT_N FROM STATION 按 LAT_N 分组 )

            select cast(lat_n as decimal(10,4)) from cte
            where rw=
            (select (count(rw)/2 )+1 from cte)
            

            【讨论】:

            • 为您的答案提供一些背景信息。与其他解决方案相比,它有什么作用?它在堆栈中添加了什么?
            【解决方案9】:

            MySQL:

            select round(s.lat_n,4) from station s where (select round(count(id)/2)-1 from station) = (select count(s1.id) from station s1 where s1.lat_n > s.lat_n);
            

            当 subquery-1 即表中一半行的索引计数和子查询 2 返回大于相应 s.lat_n 的 s1.lat_n 的数量时,两个子查询将相等。

            【讨论】:

              【解决方案10】:

              这适用于 mySQL:

              • 对列lat_n中的值进行排序
              • 每行的索引。
              • 如果列中的值的计数是奇数,则查找排序列表中间的项目的值。或者如果is是偶数,则求排序列表中间的两项的值,计算平均值并返回。

              SET @rowindex := -1;

              SELECT
                 round(AVG(lat_n),4)
              FROM
                 (SELECT @rowindex:=@rowindex + 1 AS rowindex, lat_n
                  FROM station
                  ORDER BY lat_n) 
                  AS g
              WHERE
              g.rowindex IN (FLOOR(@rowindex / 2) , CEIL(@rowindex / 2));
              

              【讨论】:

                【解决方案11】:
                declare @Position int
                set @position = round((select count(LAT_N)/2 from STATION),0)
                
                select convert(decimal(20,4),LAT_N) from STATION
                order by LAT_N
                offset @position rows
                fetch next 1 row only
                

                【讨论】:

                  【解决方案12】:

                  样本中位数的简单解释: 在单个系列中(如果观察次数非常少),第一个必须按顺序排列所有观察。 那么 count(n) 是给定数据中的观察总数。

                  如果 n 是奇数,则中位数 (M) = 第 ((n + 1)/2) 项的值。

                  如果 n 是偶数,则中位数 (M) = [(n/2)th item term + (n/2 + 1)th item term]/2

                  CTE in Sql Server

                  查询:

                  declare @cont int,@reccount int,@first int, @second int;
                  set @reccount=(select COUNT(id) from STATION);
                  IF @reccount%2=0 --even rows
                  set @cont=(((@reccount)/2)+(((@reccount)/2)+1))/2; 
                  ELSE 
                  set @cont=((select count(id) from station)+1)/2;
                  --creating CTE
                  WITH Station_CTE (rowNum, Lat_n)
                  AS (
                  select row_number() over(order by lat_n desc) as 'rowNum',lat_n from station
                  )
                  SELECT top(1) SUBSTRING(convert(varchar(30),ROUND((scte.lat_n),4)),1,(CHARINDEX('.',ROUND((scte.lat_n),4),1)+4)) from Station s inner join Station_CTE as scte on scte.rowNum =@cont
                  

                  预期输出:

                  83.8913
                  

                  【讨论】:

                    【解决方案13】:

                    最简单的方法是使用median()函数:

                    select median(lat_n)
                    from stations;
                    

                    您可以使用round()to_char() 等函数对值进行四舍五入。

                    【讨论】:

                    • 此功能仅在Oracle中可用。
                    • @Wiebke 。 . .该问题已标记为 Oracle。
                    【解决方案14】:

                    这是一种选择。我们可以分配一个行号,同时计算总表数。那么对于偶数条记录的表,我们可以取中间两条记录的平均值作为中位数。对于奇数表,我们可以取中间的记录。

                    WITH cte AS (
                        SELECT s.*,
                            ROW_NUMBER() OVER (ORDER BY lat_n) rn,
                            COUNT(*) OVER () cnt
                        FROM station s
                    )
                    
                    SELECT AVG(lat_n)
                    FROM cte
                    WHERE
                        (MOD(cnt, 2) = 0 AND rn IN (FLOOR(cnt/2), FLOOR(cnt/2) + 1)) OR
                        (MOD(cnt, 2) = 1 AND rn = FLOOR(cnt/2) + 1);
                    

                    Demo

                    注意:对于偶数记录的表,应该很明显没有确切的中位数/中间记录。但在这种情况下,许多统计学家只报告了中间一对记录的平均值。

                    【讨论】:

                      猜你喜欢
                      • 2015-08-28
                      • 2017-08-29
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多