我有以下destination
和表格:image
destination_image
(MYSQL):
- 目的地:id_destination
- 图片:id_image、文件路径、大小
- 目的地图像:id_destination,id_image
我需要为每个目的地选择给定大小的随机N 幅图像;其中 N 是在运行时定义的,目的地是从 的范围内选择的id_destination
。
我不需要top
N 张图片,只需要随机的N 张图片。
有人可以指出正确的 SQL 查询的正确方向吗?
如果您想要每个目的地的“x”个条目,您可以按 MySQL 变量执行...类似
select
di.id_destination,
di.id_image,
i.filepath,
i.size,
@RandSeq := if( @lastDestination = di.id_destination, @RandSeq +1, 1 ) as FinalSeq,
@lastDestination := di.id_destination as carryForward
from
destination_image di
join image i
on di.id_image = i.id_image,
( select @lastDestination := 0,
@RandSeq := 0 ) SQLVars
where
di.id_destination between rangeStart and rangeEnd (or similar criteria for your "range" )
having
FinalSeq = 4 ( just a sample, but your "N" entries per destination desired)
order by
id_destination,
rand()
这将在每个目的地获得 4 个(或在您的情况下为“N”个)条目。关键是顺序。order by 将首先按此顺序返回记录,然后应用 @sql 变量。因此,在每个目的地上,行将首先被 RAND()omized,但在单个目的地内是随机的......在下一个目的地上也是如此,下一个......然后@vars 生成 1、2、3等,用于“FinalSeq”列。“HAVING”子句限制哪些行允许在最后一行返回具有该条件的条目,因此每个示例只有 4 个。
SQL 的澄清。
@variables 几乎就像 SQL 语句中使用的内联变量...通过执行 ( select @someVar := someValue, @anotherVar := '', @someDateVar := getdate() ) 作为 SQLVars ...基本上只是创建和初始化可以针对查询将要处理的每一行设置、更改和更新的变量...在 SQL 语句的末尾,然后释放变量。有些人将它们预先声明为单独的 SET 命令,然后运行 SQL-Select .. 我更喜欢内联。
现在,它们是如何使用的......它们可用于跟踪 SQL-select 语句返回的任何行的几乎任何内容,但是如果您需要按特定顺序进行处理,则首先处理 order 子句,然后传递记录要使用@vars 处理...因此,请考虑在程序中设置@vars。它们按照它们在 SQL 命令中的处理顺序被设置为一个,无论最终结果是什么,都像任何其他类似的函数调用一样存储到最终的列名中,例如填充、修剪、上层、合并等。
现在,发生了什么...让我们看一下步骤...为便于理解,假设我们有一个表,10 行对应 1=A,2=B,3=C --- 10= J。这些是记录的自然顺序,例如自动增量。现在,如果您要通过 rand() 运行查询 select * from table order,您可能会得到 3-C、9-I、2=B、7=G 等……这只有 LIMIT 4返回前 4 个,你就完成了。
现在,分别采用记录 1-10 = AJ 的相同场景。现在,让我们扩展以允许您的多个目的地和大小的“组”,例如...
ID Ltr Dest Size
1 A X a
2 B Y a
3 C X a
4 D X a
5 E Y b
6 F X c
7 G Y b
8 H X a
9 I Y a
10 J X b
11 K X a
12 L Y a
13 M X a
14 N Y a
现在,您想要所有目的地的东西,但例如一个单一尺寸的“a”......我添加了一些额外的东西。
select * from SampleTable where Size="a" order by rand()
您可以获得所有“X”目的地,或“Y(a)”记录和“X(a)”记录,或其他类似的可用余额。但是,不能保证您获得 3 个“X”和 3 个“Y”大小为“a”的记录。如果您将 ORDER 更改为 ORDER BY Dest, rand(),这会将所有“X”条目放在首位,然后是“Y”,限制不起作用......所以,应用我的选择原则,你按目的地和随机排序,并应用一个 Size = "a" 的 where 子句,您可能会得到......(首先按目的地,然后随机......
13 M X a
3 C X a
8 H X a
1 A X a
11 K X a
4 D X a
9 I Y a
14 N Y a
2 B Y a
12 L Y a
现在,将@variables 应用到混合...只需应用@RandSeq 和@lastDestination
@RandSeq := if( @lastDestination = di.id_destination, @RandSeq +1, 1 ) 作为 FinalSeq,@lastDestination := di.id_destination 作为 carryForward
Start Value of
ID Ltr Dest Size @RandSeq @lastDestination FinalSeq carryForward
13 M X a 0 '' 1 X (current record value of dest)
3 C X a 1 X 2 X
8 H X a 2 X 3 X
1 A X a 3 X 4 X
11 K X a 4 X 5 X
4 D X a 5 X 6 X
9 I Y a 6 X 1 Y (change to Y resets counter to 1)
14 N Y a 1 Y 2 Y
2 B Y a 2 Y 3 Y
12 L Y a 3 Y 4 Y
现在,如果您应用“HAVING”子句 FinalSeq <= 3,您将获得上面列出的所有 FinalSeq <= 3 行,目标“X”的剩余 4、5、6 将被忽略,“ Y" 将被忽略...因此从给定大小的每个目的地留下 3 个。
希望这可以澄清查询的情况。
尝试类似ORDER BY RAND() LIMIT N
whereN
应该返回的结果数。例如:
SELECT i.id_image FROM image i
JOIN destination_image di ON i.id_image = di.id_image
WHERE di.id_destination > N AND di.id_destination < M
AND i.size = X
ORDER BY RAND() LIMIT Y
将N
、M
和替换为您X
的Y
值。