2012-03-01 47 views
3

我有一些MySQL的结果是这样的:将结果限制为n个唯一的列值?

--------------------------- 
| name | something_random | 
--------------------------- 
| john | ekjalsdjalfjkldd | 
| alex | akjsldfjaekallee | 
| alex | jkjlkjslakjfjflj | 
| alex | kajslejajejjaddd | 
| bob | ekakdie33kkd93ld | 
| bob | 33kd993kakakl3ll | 
| paul | 3k309dki595k3lkd | 
| paul | 3k399kkfkg93lk3l | 
etc... 

这正好为结果的行1000的。我需要将结果数量限制为前50个唯一名称。我认为这是一个简单的解决方案,但我不确定。

我试过使用派生表和变量,但不能完全到达那里。如果我能想出每次名称不同时如何增加一次变量,我想我可以说WHERE variable <= 50

修订

我已经试过了内部连接方法(ES)以下建议。问题是这样的:

子选择SELECT DISTINCT name FROM testTable LIMIT 50抓住前50个不同的名称。也许我在原始文章中不够清楚,但这太限制了我的查询。在我的查询中,并不是表中的每个名字都返回结果中。让我修改我的原始示例:

---------------------------------- 
| id | name | something_random | 
---------------------------------- 
| 1 | john | ekjalsdjalfjkldd | 
| 4 | alex | akjsldfjaekallee | 
| 4 | alex | jkjlkjslakjfjflj | 
| 4 | alex | kajslejajejjaddd | 
| 6 | bob | ekakdie33kkd93ld | 
| 6 | bob | 33kd993kakakl3ll | 
| 12 | paul | 3k309dki595k3lkd | 
| 12 | paul | 3k399kkfkg93lk3l | 
etc... 

所以我在这里添加了一些id号。这些ID号码与表格中的人员姓名相关。因此,您可以在结果中看到,表中不是每个人都必须在结果中(由于某个WHERE条件)。因此,在列表中的第50个独立的名称将始终有一个ID号高于49. 50人可能是编号79,234,4954等..

所以回到问题。子选择SELECT DISTINCT name FROM testTable LIMIT 50选择表格中的前50个名称。这意味着我的搜索结果将仅限于ID为< = 50的名称太紧密。如果某些名称在查询中没有显示(由于某个WHERE条件),那么它们仍被视为50个不同名称之一。所以你最终得到的结果太少了。

更新2

要@trapper:这是什么我的查询看起来像一个基本的简化:

SELECT 
    t1.id, 
    t1.name, 
    t2.details 
FROM t1 
LEFT JOIN t2 ON t1.id = t2.some_id 
INNER JOIN 
    (SELECT DISTINCT name FROM t1 ORDER BY id LIMIT 0,50) s ON s.name = t1.name 
WHERE 
    SOME CONDITIONS 
ORDER BY 
    t1.id, 
    t1.name 

而且我的结果是这样的:

---------------------------------- 
| id | name |   details | 
---------------------------------- 
| 1 | john | ekjalsdjalfjkldd | 
| 3 | alex | akjsldfjaekallee | 
| 3 | alex | jkjlkjslakjfjflj | 
| 4 | alex | kajslejajejjaddd | 
| 6 | bob | ekakdie33kkd93ld | 
| 6 | bob | 33kd993kakakl3ll | 
| 12 | paul | 3k309dki595k3lkd | 
| 12 | paul | 3k399kkfkg93lk3l | 
... 
| 37 | bill | kajslejajejjaddd | 
| 37 | bill | ekakdie33kkd93ld | 
| 41 | matt | 33kd993kakakl3ll | 
| 50 | jake | 3k309dki595k3lkd | 
| 50 | jake | 3k399kkfkg93lk3l | 
---------------------------------- 

的结果在id = 50处停止。列表中不包含50个不同的名称。只有大约23个不同的名字。

+0

LIMIT 0,50无关与ID行。它盲目地从整个结果集中取0到50行并返回它们。因此,只要在他之前不超过49个独特的名字,你就会很高兴地获得名字'jim',id '79,234,4954'。 – trapper 2012-03-02 18:03:06

+0

@trapper看看我上面的第二个更新。 – 2012-03-02 18:29:25

+0

你的'WHERE'条件可能在错误的地方,它应该放在括号内的'SELECT'中,除非你想在*已经把它缩减到50个名字后将它应用到结果*。 – trapper 2012-03-02 21:43:31

回答

4

My MySql语法可能很生疏,但是想法是使用查询来选择前50个不同的名称,然后对名称进行自联接,并从联接中选择名称和其他信息。

select a.name, b.something_random 
from Table b 
    inner join (select distinct name from Table order by RAND() limit 0,50) a 
     on a.name = b.name 
+0

我会尝试这种方法。这实质上是执行2个查询?或2 * num_of_unique_names查询?另外,你为什么内心加入一个表与自己? – 2012-03-01 23:40:21

+0

希望您有一个名称索引,它将导致索引扫描加上同一个表上的索引连接。我想你可以调用这2个查询,但使用游标的时间很短,我不知道你会怎么做。根据您的数据,使用光标可能会更糟糕,即全表扫描。当然,您需要名称索引来避免加入。 – tvanfosson 2012-03-01 23:43:15

+0

@Jakobud--与此相关的一个潜在问题是,您可能会得到排名前50的字母名称。如果是这样,你可能想要抛出一个'Order By RAND()' - 再一次,我的语法可能需要一些修正。 – tvanfosson 2012-03-01 23:50:07

2
SELECT DISTINCT name FROM table LIMIT 0,50 

编辑:啊,是我误解了问题的第一次,本应该做的伎俩虽然:)

SELECT a.name, b.something_random 
FROM `table` b 
INNER JOIN (SELECT DISTINCT name FROM `table` ORDER BY RAND() LIMIT 0,50) a 
    ON a.name = b.name ORDER BY a.name 

这项工作是怎样的(SELECT DISTINCT name FROMORDER BY RAND() LIMIT 0,50)的部分是什么翻出名称,包括在加入。所以我在这里随机抽取了50个独特的名字,但是如果你愿意的话,你可以把它改成任何其他的选择标准。

然后你将这些结果加回到你的表中。这将这50个选定名称中的每一个都链接到所有具有匹配名称的行,以获得最终结果。最后ORDER BY a.name只是为了确保每个名字的所有行最终分组在一起。

+0

所有似乎只是将结果限制为50行。我想你误解了我的问题。返回的行数是任意的。我只需要将结果限制在前50个不同的名称。返回的行数可能是任何数字> 50. – 2012-03-01 23:38:57

+0

已更新的答案 – trapper 2012-03-02 17:59:00

1

这应做到:

SELECT tA.* 
FROM 
    testTable tA 
INNER JOIN 
    (SELECT distinct name FROM testTable LIMIT 50) tB ON tA.name = tB.name 
; 
+0

正如在tvanfosson的类似答案中指出的那样,子查询中的select可能需要以某种方式(或通过RAND())进行排序以获得您想要的结果。 – StudyOfCrying 2012-03-01 23:51:42

+0

这让我更接近,看看我上面的更新。 – 2012-03-02 16:15:00

相关问题