1

我有以下destination和表格:imagedestination_image

(MYSQL):

  • 目的地:id_destination
  • 图片:id_image、文件路径、大小
  • 目的地图像:id_destination,id_image

我需要为每个目的地选择给定大小的随机N 幅图像;其中 N 是在运行时定义的,目的地是从 的范围内选择的id_destination

我不需要topN 张图片,只需要随机的N 张图片。

有人可以指出正确的 SQL 查询的正确方向吗?

4

2 回答 2

1

如果您想要每个目的地的“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 个。

希望这可以澄清查询的情况。

于 2012-06-18T14:43:40.530 回答
1

尝试类似ORDER BY RAND() LIMIT NwhereN应该返回的结果数。例如:

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

NM和替换为您XY值。

于 2012-06-18T13:56:45.843 回答