【问题标题】:SQL: How to select items from a table with the highest percentage of changeSQL:如何从更改百分比最高的表中选择项目
【发布时间】:2014-01-24 07:12:54
【问题描述】:

好吧,我完全被难住了。

我有一张桌子 GROCERY_PRICES。

其中包含 GROCERY_ITEM、PRICE_IN_2012 和 ESTIMATED_PRICE_IN_2042 的数据。

我需要编写一个 SQL SELECT 语句来查找价格上涨百分比最高的商品。然后按 GROCERY_ITEM 排序。

我终其一生都无法弄清楚如何使用表格中的数据来获取该时间段内变化百分比最高的三个项目。

这是我拥有的代码,它返回我需要的所有数据,但针对每个 GROCERY_ITEM 而不是变化百分比最高的三个项目。我知道是 310,但我无法将那个数字硬编码进去。

SELECT grocery_item, 
       price_in_2012, 
       ESTIMATED_PRICE_IN_2042, 
       sum((ESTIMATED_PRICE_IN_2042 - PRICE_IN_2012) / PRICE_IN_2012) * 100 as Percent_Change
FROM grocery_prices 
GROUP BY grocery_item, 
         price_in_2012, 
         ESTIMATED_PRICE_IN_2042
ORDER BY grocery_item;

我知道我需要使用子查询,但我不知道如何去做。

谢谢。

编辑:一些示例数据:

【问题讨论】:

  • 您使用的是什么 DBMS(MySQL、SQL Server、Oracle,...)?
  • 你能提供几行你的表中的样本数据吗?也许是我,但你的 GROUP BY 对我来说毫无意义
  • @peterm 我正在使用 Oracle SQL Developer,我已对其进行了标记,但显然有人删除了该标记。
  • @petrem 我不确定如何在此处添加表格中的数据...我会尝试...E_001 0.62 1.78 | B_001 0.8 3.28 | B_002 2.72 7.36 | M_004 2.7 5.65 | T_006 5.7 6.65 | R_003 4 16.4 | G_010 8 32.8
  • 这样,GROCERY_ITEM PRICE_IN_2012 ESTIMATED_PRICE_IN_2042 | GROCERY_ITEM PRICE_IN_2012 ESTIMATED_PRICE_IN_2042 等等。

标签: sql oracle subquery max


【解决方案1】:

你在寻找这样的东西吗?

SELECT grocery_item, price_in_2012, estimated_price_in_2042, percent_change
  FROM
(
  SELECT grocery_item, price_in_2012, estimated_price_in_2042, 
         ROUND((estimated_price_in_2042 - price_in_2012) / price_in_2012 * 100, 2) AS percent_change,
         ROW_NUMBER() OVER (ORDER BY ABS((estimated_price_in_2042 - price_in_2012) / price_in_2012 * 100) DESC) AS rank
    FROM grocery_prices t
) q
 WHERE rank <= 3;

输出:

|杂货_项目 | PRICE_IN_2012 | ESTIMATED_PRICE_IN_2042 | PERCENT_CHANGE | |-------------|--------------|---------- -------|----------------| | B_001 | 0.8 | 3.28 | 310 | | G_010 | 8 | 32.8 | 310 | | R_003 | 4 | 16.4 | 310 |

根据您的需要,您可能希望使用DENSE_RANK() 而不是ROW_NUMBER()

SELECT grocery_item, price_in_2012, estimated_price_in_2042, percent_change
  FROM
(
  SELECT grocery_item, price_in_2012, estimated_price_in_2042, 
         ROUND((estimated_price_in_2042 - price_in_2012) / price_in_2012 * 100, 2) AS percent_change,
         DENSE_RANK() OVER (ORDER BY ABS((estimated_price_in_2042 - price_in_2012) / price_in_2012 * 100) DESC) AS rank
    FROM grocery_prices t
) q
 WHERE rank <= 3;

输出:

|杂货_项目 | PRICE_IN_2012 | ESTIMATED_PRICE_IN_2042 | PERCENT_CHANGE | |-------------|--------------|---------- -------|----------------| | B_001 | 0.8 | 3.28 | 310 | | G_010 | 8 | 32.8 | 310 | | R_003 | 4 | 16.4 | 310 | | E_001 | 0.62 | 1.78 | 187.1 | | B_002 | 2.72 | 7.36 | 170.59 |

这里是SQLFiddle演示

【讨论】:

  • 是的,就是这样。哦,所以如果我想从 percent_change 中进行选择,我必须早点列出它,然后在我的子查询中定义它包含的内容,等等。但是我确实有一个问题,您将如何使用 percent_change 列上的 max 函数来做到这一点?我试图简单地获取从百分位方程返回的最大值,而不是返回最大值,我只是获取每个项目的值,而不是具有最大百分比变化的三个项目。
  • 如果您想返回 TOP N,其中 N > 1,(在您的情况下为 TOP 3)仅使用 MAX() 的集合中的行是不够的。您必须使用 order by + rownum 或使用分析窗口函数(如 ROW_NUMBER(), DENSE_RANK(), RANK())或使用带有 COUNT() 的相关子查询来使用排名。
  • 所以实际上并没有办法动态地做到这一点,所以无论有多少最大值,你只能得到那些?
  • 为什么?它是完全动态的。您只需在外部选择中告诉您想要多少条顶级记录。
  • 嗯,我明白了,无论如何,你的帮助会很好,我很感激。谢谢。
【解决方案2】:

价格上涨百分比最高的前 3 个项目

SELECT  GROCERY_ITEM,PRICE_IN_2012,ESTIMATED_PRICE_IN_2042,
ROUND(((`ESTIMATED_PRICE_IN_2042` - `PRICE_IN_2012`) / PRICE_IN_2012) * 100) AS Percent_Change
FROM grocery_prices AS itm
GROUP BY GROCERY_ITEM
ORDER BY Percent_Change DESC LIMIT 3

SQL Fiddle

希望对您有所帮助!

【讨论】:

  • OP 使用的是 Oracle,而不是 MySQL
  • 对不起,我以为是 MySQL :(
【解决方案3】:
select  *
from    im_employees a
where   (select count(distinct employee_id ) from im_employees where             employee_id>=a.employee_id)<=3;

这会为我从 im_employees 表中选择具有最大employee_id 的前 3 行。

我想这会对你有所帮助!!!

【讨论】:

  • 用 percent_change 代替 employee_id
【解决方案4】:

试试这个

select ROCERY_ITEM,PRICE_IN_2012,ESTIMATED_PRICE_IN_2042,round((cast(ESTIMATED_PRICE_IN_2042-PRICE_IN_2012 as numeric)/PRICE_IN_2012)*100,3)||'%' from GROCERY_PRICES order by round((cast(ESTIMATED_PRICE_IN_2042-PRICE_IN_2012 as numeric)/PRICE_IN_2012)*100,3) desc limit 3;

在 PostgreSQL 中

在甲骨文中

select rownum,ROCERY_ITEM,PRICE_IN_2012,ESTIMATED_PRICE_IN_2042,round(((ESTIMATED_PRICE_IN_2042-PRICE_IN_2012)/PRICE_IN_2012)*100,3)||'%' from GROCERY_PRICES  where rownum < 4 order by round((cast(ESTIMATED_PRICE_IN_2042-PRICE_IN_2012 as numeric)/PRICE_IN_2012)*100,3) desc; 

【讨论】:

    猜你喜欢
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-13
    • 1970-01-01
    相关资源
    最近更新 更多