Php 如何处理(MySQL查询):仅按DISTINCT查找最新行,其中newst one不是特定值(使用symfony2)

Php 如何处理(MySQL查询):仅按DISTINCT查找最新行,其中newst one不是特定值(使用symfony2),php,mysql,symfony,doctrine-orm,Php,Mysql,Symfony,Doctrine Orm,我工作和阅读了几个小时,除了执行未执行的查询或向代码中添加新字段和更新事件之外,我找不到任何合适的解决方案。你可以想象,这个问题快把我逼疯了 基本理念 我确实有一个名为ping的表,其中包含有关网站响应时间的信息,并且与网站 另一个名为

我工作和阅读了几个小时,除了执行未执行的查询或向代码中添加新字段和更新事件之外,我找不到任何合适的解决方案。你可以想象,这个问题快把我逼疯了

基本理念

我确实有一个名为
ping
的表,其中包含有关网站响应时间的信息,并且与
网站

另一个名为
的表包含有关该网站的数据,并且与
ping

因此,
网站
可以有多个ping,但
ping
行只能有一个网站。
到目前为止还不错

表格数据
表:ping
-带有一个示例行:

=================================================================================
|      id       |  website_id   |   response    | is_reachable  |  created_at   |
=================================================================================
|     6994      |      15       |      49       |       1       |  22/12/2013   |
|               |               |               |               |   12:14:23    |
---------------------------------------------------------------------------------
表格:网站
-带有一个示例行:

=================================================================================================
|      id       |  company_id   |     name      |      url      |     logo      |  description  |
=================================================================================================
|      15       |       7       |   LinkedIn    |http://www.link| linkedin.svg  |  US Website   |
|               |               |               |   edin.com    |               |               |
-------------------------------------------------------------------------------------------------

案例

我想做的是列出最后10个最慢的回答(ms)。听起来容易吗?也许我的数据库设计错了,或者我就是看不出重点。
无论如何,我需要过滤掉那些不可到达(
可到达=0
或/和
响应=null
)的人,但这不能通过
WHERE
子句来完成,因为这将显示最后一行
ping
,这不是我的目标

据我所知,这是:

        $qb = $this->createQueryBuilder('s')
            ->Select('DISTINCT(s.website)')
            ->AddSelect('s.id, s.response')
            ->AddSelect('w.id as wid, w.name')
            ->leftJoin("s.website", 'w')
            ->orderBy('s.id', 'DESC')
            ->addorderBy('s.response, 'DESC');
到目前为止,它产生了:

array (size=10)
  0 => 
    array (size=5)
      1 => string '21' (length=2)
      'id' => int 14063
      'response' => int 75
      'wid' => int 21
      'name' => string 'Google Mail' (length=11)
  1 => 
    array (size=5)
      1 => string '20' (length=2)
      'id' => int 14062
      'response' => int 27
      'wid' => int 20
      'name' => string 'Google DE' (length=9)
  2 => 
    array (size=5)
      1 => string '19' (length=2)
      'id' => int 14061
      'response' => int 25
      'wid' => int 19
      'name' => string 'Google' (length=6)
  3 => 
    array (size=5)
      1 => string '18' (length=2)
      'id' => int 14060
      'response' => null
      'wid' => int 18
      'name' => string 'Twitter DE' (length=10)
  4 => 
    array (size=5)
      1 => string '17' (length=2)
      'id' => int 14059
      'response' => null
      'wid' => int 17
      'name' => string 'Twitter UK' (length=10)
如上所述,如果您添加一个简单的
WHERE
语句,这只会导致TWITTER DE/TWITTER UK显示其最后一行
is_reachable=1
。 我不知道如何处理这个问题。感谢您的帮助

临时解决方案(选择更好的解决方案!)


这是一个典型的“查找与最大行对应的信息”问题

在不执行子请求的情况下,可以通过对表本身执行左联接来完成此操作:

SELECT w.id, s_last.id, s_last.response, w.name
FROM website w
JOIN ping s_last ON w.id = s.websiteId
# Left join on pings higher than us
LEFT JOIN ping s ON s.id > s_last.id
WHERE 
  # only take ping which has no higher ping
  s.id IS NULL
  AND
  # Filter out unreachable websites
  s_last.is_reachable = 1
ORDER BY s.response DESC
举个例子,Twitter DE和Twitter UK不会出现在结果集中,因为我们上次尝试时没有找到它们。(阿法尤,这就是你想要的)


尽管如此,我不知道它是否适用于有很多结果的数据。如果性能不够好,请尝试将最后一次ping保存到另一个表中。

正在查找最后10个最慢的响应或最后10个最慢的网站,-或者每个网站最近10个最慢的响应?通过最后一次
ping查看最慢的
网站
。上面的列表(数组)很好,除了Twitter DE和Twitter UK,其中最实际的ping实际上是离线的,所以不应该显示。
在w.id=s.website_id
上最后一次加入ping s,因为它无法在定义
左加入ping s
之前访问s.website_id。无论如何,我猜这是一个典型的,所以我用正确的s_last.website_id替换了它,最终让查询成为一个。因此,结果集是非常错误的,因为它只显示了一行“GoogleMail”。此外,对于6.000行(这是一个示例数据集),查询大约需要10秒。真正的那个要大得多。我还与一位朋友讨论了我的问题,提出了一个不同的问题。请参阅问题帖。
SELECT w.id, s_last.id, s_last.response, w.name
FROM website w
JOIN ping s_last ON w.id = s.websiteId
# Left join on pings higher than us
LEFT JOIN ping s ON s.id > s_last.id
WHERE 
  # only take ping which has no higher ping
  s.id IS NULL
  AND
  # Filter out unreachable websites
  s_last.is_reachable = 1
ORDER BY s.response DESC