简体   繁体   English

MySQL 联合和重复

[英]MySQL Union and Duplicates

This is a short snippet of a very long query with about 6 unions but they are all roughly the same logic:这是一个很长的查询的一小段,大约有 6 个联合,但它们的逻辑大致相同:

(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) 

In the second query, the rarity is set depending on chance calculated in PHP.在第二个查询中,根据在 PHP 中计算的机会设置稀有度。 So I get a random number and if it's under 5 the rarity is " Rare " but if it's over 5 the rarity is " Common ".所以我得到一个随机数,如果它低于 5,则稀有度为“ Rare ”,但如果超过 5,则稀有度为“ Common ”。

The problem now arises when it gets " Common ", sometimes the query will choose a common that was already selected in the first query ( I don't want duplicates ).现在当它获得“ Common ”时出现问题,有时查询会选择在第一个查询中已经选择的公共(我不想要重复)。 Is it possible to work around this?有可能解决这个问题吗? How can I make it so that it avoids picking a duplicate which will get stripped by the UNION ?我怎样才能避免选择会被UNION剥离的重复项?

MySQL Version 5.7.30 MySQL 版本 5.7.30

DB Fiddle Example: https://www.db-fiddle.com/f/7wFDnYuVPt15qPorQvemrw/4 DB小提琴示例: https://www.db-fiddle.com/f/7wFDnYuVPt15qPorQvemrw/4

Further explanation :进一步解释

What I need: Always return 3 unique rows using this UNION .我需要什么:始终使用此UNION返回 3 个唯一行。

Problem: It sometimes returns 2 rows as the second query can end up picking a row that was already chosen in the first query.问题:它有时会返回 2 行,因为第二个查询最终会选择在第一个查询中已经选择的行。

UNION ALL will not work as it will return duplicates. UNION ALL将不起作用,因为它会返回重复项。

I would change the variable parts of the query.我会更改查询的可变部分。 Right now your parameter is set_rarity ( cr.set_rarity =? ).现在你的参数是set_rarity ( cr.set_rarity =? )。 I would let it be fixed to "Rare", but make the LIMITs variable.我会让它固定为“稀有”,但使 LIMITs 变量。

Assuming you have something like this in your PHP code:假设您的 PHP 代码中有这样的内容:

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

I would change it to:我会将其更改为:

$commonLimitParam = 2;
$rareLimitParam = 0;

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

and bind the above parameters into tghe following 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 ?)

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 ?) 

Look for寻找

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

If parameter is not 'Common' then you'll get 2 'Common' rows and 3 non-'Common' row from subquery, sorting will posess 'Common' rows first and 3rd will be random of 3 non-'Common' rows.如果参数不是“Common”,那么您将从子查询中获得 2 个“Common”行和 3 个非“Common”行,排序将首先包含“Common”行,第三个将是 3 个非“Common”行的随机。

If parameter is 'Common' then you'll get 3-5 rows in subquery and select 3 random from them.如果参数是“Common”,那么您将在子查询中获得 3-5 行,并从中随机获得 select 3 行。


fiddle (based on OP's fiddle) - always returns 3 different records (if exists in source table, of course).小提琴(基于 OP 的小提琴) - 总是返回 3 条不同的记录(当然,如果存在于源表中)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM