【问题标题】:Mysql - get 6 results before and after the desired value to make comparison chartMysql - 得到想要的值前后的6个结果做对比图
【发布时间】:2014-05-01 10:46:06
【问题描述】:

今天我面临一个挑战,我可以通过多个查询、一点 PHP 和一些其他有趣的事情来解决,但我想知道我的意思是否可以通过单个查询来实现和/或存储的 fn/procedure。

我更好地解释自己: 在城市列表中,我需要获取该命名城市(例如“罗马”)的值(例如“一般费用”)。

很简单。

我想做的是: 在罗马之前和之后有 6 条相同值的记录。 所以我会看到一些东西:

| position | city      | expenses |
|    35    | Paris     | 1364775  |
|    36    | Milan     | 1378499  |
|    37    | New York  | 1385759  |
|    38    | London    | 1398594  |
|    39    | Oslo      | 1404648  |
|    40    | Munchen   | 1414857  |
|    41    | Rome      | 1425773  | ***  <--this is the value I need
|    42    | Dublin    | 1437588  |
|    43    | Athen     | 1447758  |
|    44    | Stockholm | 1458593  |
|    46    | Helsinki  | 1467489  |
|    47    | Moscow    | 1477484  |
|    48    | Kiev      | 1485665  |

这些值将填充条形图。

如您所见,还有另一个复杂程度:位置。

必须根据所有记录计算位置。

假设我有 100 条记录,我会有 1 到 100 的排名位置,但只需要输出“有限 13 条”记录。

任何链接、建议、教程或其他可以帮助我的吗? 一如既往地提前感谢您。

编辑 必须计算位置。它不是输入值。

无论如何,感谢大家的努力。

【问题讨论】:

  • 位置总是连续数字吗?
  • 必须计算位置。它不是输入值
  • 排名如何计算?

标签: php mysql sql comparison ranking


【解决方案1】:
SELECT
all_ranked.*
FROM (select rank 
      from (SELECT a.id             AS id2,
            @curRow := @curRow + 1 AS Rank
            FROM the_table a
            JOIN
                (SELECT @curRow := 0) r
                ORDER BY position DESC
            ) AS B) 
      where B.id=1234567) as rank_record, <--- just one record - value of rank
      (SELECT a.id             AS id2,
            @curRow := @curRow + 1 AS Rank
            FROM the_table a
            JOIN
                (SELECT @curRow := 0) r
                ORDER BY position DESC
            ) AS all_ranked <--- all ranked users
where all_ranked.rank>=rank_record.rank-6 and all_ranked.rank>=rank_record.rank+6

创建 2 个合并为一个的查询。第一个获取位置,第二个设置位置并剪切所需的片段

【讨论】:

  • 感谢 Stnislav。我在您的查询中收到一条错误消息,指出每个派生表都必须有自己的别名。而且位置不是输入,而是计算出来的值。
【解决方案2】:

您可以使用一个存储函数/过程,该函数/过程接收指示主题记录的输入,例如“Rome”来推导排名,我在这里将其称为该记录的感知 ID (PID),例如, 41. 然后您可以使用变量@PID 来存储该位置。

然后您可以再次进行排名查询,但选择所有记录。

SELECT .... WHERE Ranking BETWEEN (@PID-6) AND (@PID+6) 

这样做的一个好处是函数/过程可以接受一个额外的参数,以允许它获取排名之后的 X 记录和之前的 Y 记录。它也更容易阅读和维护。

在不使用 PHP 的情况下将其作为单个查询执行会很棘手,因为您需要插入一个 WHERE 子句,其中条件是另一个查询的结果。

【讨论】:

    【解决方案3】:

    如果您的位置将是连续的唯一编号,您可以在 where 条件下使用子查询。

    SELECT `position`, `city`, `expenses`
        FROM table_name
        WHERE `position` > (
          SELECT `position`-7
              FROM table_name
              WHERE `city`='Rome'
          )
        ORDER BY `position`
        LIMIT 13
    

    PS:我不是 SQL 专家。可能有更好更有效的方法。

    【讨论】:

      【解决方案4】:

      我还没有尝试过,但这应该可以:在 M​​ySQL 中选择时,您可以使用增加的变量来获得位置。然后你必须选择这个“临时表”两次;一次找到罗马,一次找到所有 13 条记录:

      select
      from
      (
        select  @rowno := @rowno + 1 as position, city, expenses
        from cities
        cross join (select @rowno := 0)
        order by expenses 
      ) 
      where abs(position - 
        (
          select position, city
          from
          (
            select  @rowno := @rowno + 1 as position, city, expenses
            from cities
            cross join (select @rowno := 0)
            order by expenses 
          )
          where city = 'Rome'
        )
      ) <= 6;
      

      【讨论】:

      • 感谢托尔斯滕。这就是我得到的:'1064 - 你的 SQL 语法有错误;查看与您的 MySQL 服务器版本相对应的手册,了解在 from ( select @rowno := @rowno + 1 as position, codice_alfanumerico_istat, ' at line 2 附近使用的正确语法,其中 codice_alfanumerico_istat 是城市的标识符
      【解决方案5】:
      SELECT rank as position,city,expenses FROM
      (SELECT @rownum := @rownum + 1 AS position, city, expenses, FIND_IN_SET( position, (
      SELECT GROUP_CONCAT( position
      ORDER BY position ASC ) 
      FROM test )
      ) AS rank
      FROM test,(SELECT @rownum := 0) r
      HAVING rank BETWEEN(SELECT  FIND_IN_SET( position, (
      SELECT GROUP_CONCAT( position
      ORDER BY position ASC ) 
      FROM test )
      )-6 AS rank
      FROM test
      WHERE expenses=1425773)
      AND
      (SELECT  FIND_IN_SET( position, (
      SELECT GROUP_CONCAT( position
      ORDER BY position ASC ) 
      FROM test )
      )+6 AS rank
      FROM test
      WHERE expenses=1425773))x
      

      FIDDLE

      【讨论】:

      • 感谢 mihai,但 position 不是输入值。必须计算。此外,我在你的小提琴中看不到罗马 :)
      • @Aptivus 已更改,忽略表格中的位置。
      • 您的查询很酷,但是在一堆 171 条记录上,+6/-6 似乎不起作用。
      • @Aptivus 将它们添加到小提琴中,我看到它有效,并且有超过 12 个。谢谢你的酷形容词,这对我来说意义重大。
      • 这里有一个FIDDLE 的真实数据。表中没有可用的 POSITION 字段。我已尝试调整您的查询,但由于 POSITION 字段而没有成功。 a01字段是居民人数,a05是一种费用,a06是另一种费用。 codice_alfanumerico_istat 字段是城市识别码。必须在 a05 上进行分析
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-14
      • 2022-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-26
      相关资源
      最近更新 更多