MySQL FIND_IN_SET результат поиска необходим в оригинальной последовательности - PullRequest
0 голосов
/ 15 февраля 2020

Я использую FIND_IN_SET в MySQL, как показано ниже:

SELECT  
        color, b.id
FROM    cards b
        where FIND_IN_SET(b.color, 'gold,gold,bronze,silver,silver') > 0
GROUP   BY b.id
        ORDER BY RAND() 
        limit 5;

И я получаю вывод, как показано ниже:

enter image description here

Однако я хочу получить карты в той же последовательности, что и в строке параметра, поставляемой для FIND_IN_SET, т. Е.

gold, gold, bronze, silver, silver

Таким образом, первая строка вывода должна быть золотого цвета, затем другое золото, затем бронза и т. д. - в той же последовательности, без какого-либо случайного поиска.

Я не могу самостоятельно соединиться, так как это большой стол. Пожалуйста, помогите.

1 Ответ

1 голос
/ 15 февраля 2020

Вам нужно будет сделать это, используя UNION из 3 запросов, чтобы найти случайных «золотых», «серебряных» и «бронзовых» медалистов, а затем упорядочить эти результаты, используя FIELD:

SELECT color, id
FROM (
    (
        SELECT color, id
        FROM cards
        WHERE color = 'gold'
        ORDER BY RAND()
        LIMIT 2
    )
    UNION ALL
    (
        SELECT color, id
        FROM cards
        WHERE color = 'bronze'
        ORDER BY RAND()
        LIMIT 1
    )
    UNION ALL
    (
        SELECT color, id
        FROM cards
        WHERE color = 'silver'
        ORDER BY RAND()
        LIMIT 2
    )
) m
ORDER BY FIELD(color, 'gold', 'bronze', 'silver')

Демонстрация по SQLFiddle

Вот способ, которым вы можете реализовать это как комбинацию PHP / MySQL:

$pack_sql_comma_separated = 'gold,silver,gold,gold,silver,gold';
$colors = explode(',', $pack_sql_comma_separated);
$counts = array_count_values($colors);
$sql = "SELECT color, id FROM (";
$subqueries = [];
foreach ($counts as $color => $count) {
    $subqueries[] = "(
        SELECT color, id
        FROM cards
        WHERE color = '$color'
        ORDER BY RAND()
        LIMIT $count
    )";
}
$sql .= implode(' UNION ALL ', $subqueries) . ') m';
// run SQL query
// ...
// assume all query results read into $rows according to medal colour, something like this
$rows = array('gold' => array(array('id' => 20),
                              array('id' => 5),
                              array('id' => 4),
                              array('id' => 27)
                              ),
              'silver' => array(array('id' => 19),
                                array('id' => 11)
                                )
             );

//display in required order
foreach ($colors as $color) {
    $card = array_shift($rows[$color]);
    echo "$color {$card['id']}\n";
}

Демонстрация на 3v4l.org

...