MySQL Союз и дубликаты - PullRequest
1 голос
/ 27 мая 2020

Это короткий фрагмент очень длинного запроса с примерно 6 союзами, но все они примерно одинаковы. c:

(SELECT cr.id, cr.price, cd.times, cd.name, cr.set_rarity, cd.type, cd.currentPrice_tcg 
FROM card_sets_rarity cr
JOIN card_database cd
ON cr.id = cd.id
WHERE cr.set_rarity = 'Common'
AND cr.set_name = 'Dark Beginning 1'
AND cd.type = 'Spell Card'
GROUP BY cd.id ORDER BY RAND() LIMIT 2)

UNION 

(SELECT cr.id, cr.price, cd.times, cd.name, cr.set_rarity, cd.type, cd.currentPrice_tcg 
FROM card_sets_rarity cr
JOIN card_database cd
ON cr.id = cd.id
WHERE cr.set_rarity = ?
AND cr.set_name = 'Dark Beginning 1'
AND cd.type = 'Spell Card'
GROUP BY cd.id ORDER BY RAND() LIMIT 1) 

Во втором запросе редкость устанавливается в зависимости от случайности Вычислено в PHP. Итак, я получаю случайное число, и если оно меньше 5, редкость - «Rare», но если оно больше 5, редкость «Common».

Теперь проблема возникает, когда оно получает «Common. ", иногда запрос выбирает общий, который уже был выбран в первом запросе ( Мне не нужны дубликаты ). Можно ли это обойти? Как я могу сделать так, чтобы он избегал выбора дубликата, который будет удален UNION?

MySQL Версия 5.7.30

Пример скрипта DB: https://www.db-fiddle.com/f/7wFDnYuVPt15qPorQvemrw/4

Дальнейшее объяснение :

Что мне нужно: всегда возвращать 3 уникальные строки, используя это UNION.

Проблема: иногда возвращает 2 строки, поскольку второй запрос может закончиться выбором строки, которая уже была выбрана в первом запросе.

UNION ALL не будет работать, поскольку он вернет дубликаты.

Ответы [ 2 ]

3 голосов
/ 27 мая 2020

Я бы изменил переменные части запроса. Сейчас ваш параметр set_rarity (cr.set_rarity = ?). Я бы установил его на "Rare", но сделал бы переменную LIMITs.

Предполагая, что у вас есть что-то вроде этого в вашем PHP коде:

if ($randomNumber > 5) {
    $rarityParam = 'Common';
} else {
    $rarityParam = 'Rare';
}

Я бы изменил его на :

$commonLimitParam = 2;
$rareLimitParam = 0;

if ($randomNumber > 5) {
    $commonLimitParam += 1;
} else {
    $rareLimitParam   += 1;
}

и свяжите указанные выше параметры в следующем запросе:

(SELECT cr.id, cr.price, cd.times, cd.name, cr.set_rarity, cd.type, cd.currentPrice_tcg 
FROM card_sets_rarity cr
JOIN card_database cd
ON cr.id = cd.id
WHERE cr.set_rarity = 'Common'
AND cr.set_name = 'Dark Beginning 1'
AND cd.type = 'Spell Card'
GROUP BY cd.id ORDER BY RAND() LIMIT ?)

UNION 

(SELECT cr.id, cr.price, cd.times, cd.name, cr.set_rarity, cd.type, cd.currentPrice_tcg 
FROM card_sets_rarity cr
JOIN card_database cd
ON cr.id = cd.id
WHERE cr.set_rarity = 'Rare'
AND cr.set_name = 'Dark Beginning 1'
AND cd.type = 'Spell Card'
GROUP BY cd.id ORDER BY RAND() LIMIT ?) 
2 голосов
/ 27 мая 2020

Найдите

SELECT *
FROM (
-- your query
(SELECT cr.id, cr.price, cd.times, cd.name, cr.set_rarity, cd.type, cd.currentPrice_tcg 
FROM card_sets_rarity cr
JOIN card_database cd
ON cr.id = cd.id
WHERE cr.set_rarity = 'Common'
AND cr.set_name = 'Dark Beginning 1'
AND cd.type = 'Spell Card'
GROUP BY cd.id ORDER BY RAND() LIMIT 2)

UNION 

(SELECT cr.id, cr.price, cd.times, cd.name, cr.set_rarity, cd.type, cd.currentPrice_tcg 
FROM card_sets_rarity cr
JOIN card_database cd
ON cr.id = cd.id
WHERE cr.set_rarity = ?
AND cr.set_name = 'Dark Beginning 1'
AND cd.type = 'Spell Card'
GROUP BY cd.id ORDER BY RAND() LIMIT 3)  -- LIMIT enlarged to 3
-- end of your query
     ) subquery
ORDER BY set_rarity != 'Common', RAND() LIMIT 3

Если параметр не является 'Common', тогда вы получите 2 'Common' строки и 3 non-Common 'строки из подзапроса, сортировка будет иметь сначала' Common 'строки и 3-я будет случайной из 3-х строк, отличных от 'Common'.

Если параметр 'Common', вы получите 3-5 строк в подзапросе и выберите 3 случайных из них.


fiddle (на основе скрипта OP) - всегда возвращает 3 разных записи (конечно, если они существуют в исходной таблице).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...