从MySql中的每个类别中选择随机N条记录(不是顶部)

时间:2012-06-18 13:54:25

标签: mysql sql

我有以下destinationimagedestination_image表:

(MYSQL):

  • 目的地:id_destination
  • image:id_image,filePath,size
  • destination_image:id_destination,id_image

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

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

有人能指出我正确的SQL查询方向吗?

2 个答案:

答案 0 :(得分:1)

尝试类似ORDER BY RAND() LIMIT N的内容,其中N是应返回的结果数。例如:

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

NMXY替换为您的值。

答案 1 :(得分: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”)条目PER Destination。关键是订单。 order by将以FIRST的顺序返回记录,然后应用@sql变量。因此,在每个目标上,行将首先被省略RAND(),但是在单个目标中随机出现...并且在下一个目标上相同,然后是下一个...然后@vars生成1,2,3等等“FinalSeq”列。 “HAVING”子句限制哪些行允许在最后一行中返回具有该条件的条目,因此每个示例只有4行。

SQL的澄清。

@variables几乎就像在SQL语句中使用的内联变量...通过执行(选择@someVar:= someValue,@ anotherVar:='',@ someDateVar:= getdate())作为SQLVars ...基本上只需创建和初始化可以根据查询要处理的每一行设置,更改和更新的变量...在SQL语句结束时,然后释放变量。有些人将它们预先声明为单独的SET命令,然后运行SQL-Select ..我更喜欢在线执行它们。

现在,如何使用它们......它们可用于跟踪SQL-select语句返回的任何行的几乎任何内容,但是如果您需要按特定顺序排序,则首先处理order子句,然后传递记录以使用@vars处理......所以,想想在程序中设置的@vars。它们按照SQL命令处理顺序设置为1,无论最终结果如何,都会像任何其他类似的函数调用一样存储到最终列名中,例如填充,修剪,上部,合并等。

现在,发生了什么......让我们来看看这些步骤......假设为了理解,我们有一个表,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 = A-J。现在,让我们展开以允许您拥有多个目的地和大小的“组”,例如......

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)”记录,或其他类似的可用余额。但是,不保证您获得大小为“a”的3“X”和3“Y”记录。如果你将ORDER改为ORDER BY Dest,rand(),这将把所有“X”条目放在第一位,那么“Y”是一个限制不起作用......所以,应用我选择的原则,你按目的地和随机排序,并应用一个大小=“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,@ popDestination:= 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&lt; = 3,您将获得上面列出的所有行,其中FinalSeq&lt; = 3,并且将忽略目标“X”的剩余4,5,6 ,“Y”中的4个将被忽略...从而从给定大小的每个目的地留下3个。

希望这可以澄清查询的内容。