mytable
pid name field
=== ==== =====
1 A1 0
2 A2 1
3 A3 1
4 A4 0
5 A5 0
这是我的表结构。这里我想随机选择4行,所以我在查询中使用RAND()mysql函数 我的问题是
如何配对行。我的意思是,我想选择pid 2和3总是另一个。 我需要按照下面的顺序。 我不想破坏对A2 A3
A1 A2 A3 A4
或A2 A3 A4 A1
或A2 A3 A4 A5
或A4 A5 A2 A3
等
我使用了下面的查询,但它不适合我
SELECT * FROM mytable ORDER BY RAND() ASC limit 0,4
答案 0 :(得分:11)
(
SELECT *
FROM `mytable`
WHERE
name ='A2' OR
name ='A3'
LIMIT 2
)
UNION
(
SELECT DISTINCT *
FROM `mytable`
WHERE
name !='A2' OR
name !='A3'
ORDER BY RAND( ) LIMIT 2
)
ORDER BY `pid`
答案 1 :(得分:6)
通常,使用ORDER BY RAND()不是一个好主意。请阅读Jan Kneschke的文字,说明原因:http://jan.kneschke.de/projects/mysql/order-by-rand/
答案 2 :(得分:2)
我对此进行了严格的测试,通过了。
(
SELECT * , 0.5 AS ordercol
FROM `mytable`
WHERE `name`IN ( "A2", "A3" )
LIMIT 2
)
UNION (
SELECT * , rand() AS ordercol
FROM `mytable`
WHERE `name` NOT IN ( "A2", "A3" )
LIMIT 2
)
ORDER BY ordercol, `name` IN ( "A2", "A3" ) , `name` ="A3"
这将很好地完成这项工作。但是为了使结果更加随机,请执行该语句,将第一行中的0.5值替换为客户端应用程序代码(如PHP中的mt_rand(0, 1000000) / 1000000
)选择的随机值。确保它介于0和1之间。但 NOT 使用mysql函数rand()
代替0.5,因为它会使A2和A3彼此分开。 诀窍是在所有行中为“ordercol”分配一个随机值,但为A2和A3保持相同
编辑: 我相信我们可以用LEFT JOIN替换0.5值,而不是依靠PHP的离散值,因为我们替换了union的第一段,所以整个查询变为:
(
SELECT mt1.* , mt2.ordercol AS ordercol
FROM `mytable` AS mt1
LEFT JOIN (
SELECT RAND( ) AS ordercol
) AS mt2 ON TRUE
WHERE `name`
IN (
"A2", "A3"
)
LIMIT 2
)
UNION (
SELECT * , rand() AS ordercol
FROM `mytable`
WHERE `name` NOT IN ( "A2", "A3" )
LIMIT 2
)
ORDER BY ordercol, `name` IN ( "A2", "A3" ) , `name` ="A3"
答案 3 :(得分:1)
我怀疑在MySQL中只有一种理智的方法。
假设您使用的是PHP / MySQL,我可以想到一种方法:
基本上你查询除A3以外的所有内容,然后将A3放在A2旁边
$res = mysql_query("SELECT name, field FROM mytable WHERE name <> 'A3' ORDER BY RAND()");
$res2 = mysql_query("SELECT name, field FROM mytable WHERE name = 'A3'");
$data = array();
while($row = mysql_fetch_array($res))
{
array_push($data, $row);
if ($row['name'] == "A2")
{
$row2 = mysql_fetch_array($res2);
array_push($data, $row2);
}
}
现在$ data将按所需顺序包含您的结果。
答案 4 :(得分:1)
如果您总是选择表格中的所有行:
SELECT pid, name, field, idx
FROM (
SELECT pid, name, field,
@pos := IF(name = 'A3', @idx, @pos),
@idx := @idx + IF(name = 'A3', 2, 1), idx
FROM mytable, (SELECT @pos = -1, @idx := 0) dm
WHERE name <> 'A2'
ORDER BY RAND()
)
UNION SELECT pid, name, field, @pos + 1 idx
FROM mytable
WHERE name = 'A2'
ORDER BY idx;
如果您并不总是返回所有行,则需要检查是否返回A3
以了解是否应包含A2
:
SELECT pid, name, field, idx
FROM (
SELECT pid, name, field,
@pos := IF(name = 'A3', @idx, @pos),
@idx := @idx + IF(name = 'A3', 2, 1), idx
FROM mytable, (SELECT @pos = -1, @idx := 0) dm
WHERE name <> 'A2'
ORDER BY RAND()
LIMIT 4
)
UNION SELECT pid, name, field, @pos + 1 idx
FROM mytable
WHERE @pos != -1 AND name = 'A2'
ORDER BY idx;
答案 5 :(得分:0)
SELECT * FROM (
SELECT DISTINCT name FROM mytable
WHERE name <> 'A2' AND name <> 'A3'
ORDER BY RAND()
LIMIT 0,2
UNION
SELECT DISTINCT name FROM mytable
WHERE name = 'A2' OR name = 'A3'
ORDER BY name
)whateverQueryAlias
ORDER BY RAND()
应该这样做。
答案 6 :(得分:0)
这是我的解决方案:
SELECT *
FROM `mytable`
WHERE name ='A2'
OR name ='A3'
LIMIT 2
UNION
(SELECT DISTINCT *
FROM `mytable`
WHERE name !='A2'
OR name !='A3'
ORDER BY RAND( ) LIMIT 2) ORDER BY RAND()
答案 7 :(得分:0)
SELECT *,RAND()&#34; xrand&#34;来自yourtable A ORDER BY xrand LIMIT 4
答案 8 :(得分:-1)
SELECT * FROM `mytable` order by rand(), name asc limit 4.
我认为这将满足您的需求。