【问题标题】:MySQL result with multiple occurance of an element depending on importanceMySQL 结果根据重要性多次出现一个元素
【发布时间】:2011-09-05 09:37:52
【问题描述】:

谁能告诉我是否可以根据每一行的重要性获取一个 mysql 条目列表。假设我在一个表中有 4 个条目(ID、名称、重要性)。 0 = 最高重要性。

id | file      | importance
---|-----------|-----------
1  | movie.mp4 | 0
2  | image.jpg | 1
3  | movie1.mp4| 2
4  | movie2.mp4| 2

想要创建一个包含 20 个输入的数组,其中填充了 4 个元素的结果(例如 5*movie.mp4、3*image.jpg、2*...、2*...),但是诀窍是元素必须随机放置在数组中,而不是一个接一个。

$file[] = movie.mp4;
$file[] = movie2.mp4;
$file[] = image.jpg;
$file[] = movie.mp4;
$file[] = image.jpg;
$file[] = movie1.mp4;
$file[] = movie.mp4;
$file[] = image.jpg;
$file[] = movie.mp4;
$file[] = movie1.mp4;
$file[] = movie.mp4;
$file[] = movie2.jpg;

希望你明白这一点,否则请询问:)

【问题讨论】:

  • 请改写您的问题标题,与您提供的描述无关

标签: mysql arrays random sql-order-by


【解决方案1】:
SELECT draw_bucket.file
FROM (
    SELECT row,
    FLOOR( RAND() * ( SELECT SUM( POW( 2, 2 - importance ) ) FROM files ) ) AS rnd
    FROM ( 
       (SELECT 1 AS row) UNION (SELECT 2) UNION (SELECT 3) UNION (SELECT 4) UNION
       (SELECT 5) UNION (SELECT 6) UNION (SELECT 7) UNION (SELECT 8) UNION
       (SELECT 9) UNION (SELECT 10) UNION (SELECT 11) UNION (SELECT 12) UNION
       (SELECT 13) UNION (SELECT 14) UNION (SELECT 15) UNION (SELECT 16) UNION
       (SELECT 17) UNION (SELECT 18) UNION (SELECT 19) UNION (SELECT 20)
    ) AS row_nums
) AS rows
INNER JOIN (
    SELECT @row := @row + 1 AS row, file
    FROM ( 
       (SELECT 1 AS cnt) UNION (SELECT 2) UNION (SELECT 3) UNION (SELECT 4)
    ) AS cnt
    INNER JOIN files
    ON( cnt.cnt <= POW( 2, 2 - files.importance ) )
    INNER JOIN ( SELECT @row := -1 ) AS INIT
) AS draw_bucket
ON( rows.rnd = draw_bucket.row )

row_nums 子查询中的(SELECT 1), (SELECT 2), ... 数应等于您想要的条目数,cnt 子查询中应等于 2 ^ minimumPriority。

您可以通过在 PHP 中完成大部分工作来简化这一点(例如)。执行SELECT * 并像这样填充数组:

$items = array(
    array( 'file' => 'movie.mp4', 'importance' => 0 ),
    array( 'file' => 'image.jpg', 'importance' => 1 ),
    array( 'file' => 'movie1.mp4', 'importance' => 2 ),
    array( 'file' => 'movie2.mp4', 'importance' => 2 )
);

然后在 PHP 中进行绘图:

$minImportance = 2;

$drawBucket = array();
foreach( $items as $index => $item ) {
    for( $i = 0; $i < pow( 2, $minImportance - $item['importance'] ); ++$i ) {
        $drawBucket[] = $index;
    }
}

$output = array();
for( $i = 0; $i < 20; ++$i ) {
    $randomIndex = mt_rand( 0, count($drawBucket) - 1 );
    $output[] = $items[ $drawBucket[$randomIndex] ][ 'file' ];
}

var_dump( $output );

【讨论】:

  • 感谢您的回复 :) 这会创建数组,是的,但它不会每次都使用最重要的文件。目标是在创建数组时让重要文件比其他任何文件都更频繁地出现在数组中,并切换文件,因此同一文件不会再次出现。
  • @Fløtti 正是你想要的,重要文件出现的频率更高,仔细查看,我们将更多的重要文件放在 draw_bucket 中,两个代码都经过测试。
  • 是的,运行几次后,我可以看到它确实占用了重要文件。现在唯一的问题是确保它不会将同一个文件打印出两次,例如“元素 3 和 4”。
  • @Fløtti 这几乎不可能合并到 MySql 代码中,但在 PHP 代码中添加一个变量到第二个循环以跟踪先前绘制的文件,如果它与当前文件绘制相同直到不一样为止。
  • 谢谢,现在我创建了一个 fench post 解决方案,以确保获得第一个条目并检查其余元素。我就是这样做的: $output = array(); $randomIndex = mt_rand(0, count($drawBucket) - 1); $output[0] = $items[ $drawBucket[$randomIndex] ][ 'name' ]; for( $i = 1; $i
【解决方案2】:

我们可以用 php 简单地做到这一点:

<?php
function cmpf(a,b)
{
    return a['importance'] - b['importance'];
}
$arr = array();
$res = mysql_query("SELECT * from tbname ORDER BY importance;");
$k = 0;
while ($row = mysql_fetch_assoc($res))
{
  $arr[$k] = $row;
  $k++
}
shuffle($arr);
usort($arr, "cmpf");
?>

【讨论】:

    猜你喜欢
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-09
    • 2020-05-17
    • 1970-01-01
    • 2016-11-05
    • 2021-03-21
    相关资源
    最近更新 更多