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