我必须根据来自2个不同表的多个记录将一些记录插入表中。
表:
目标:player_list_items
来源1 :list_items
来源2 :map_details
玩家应该播放包含项目列表的列表;列表需要在地图上播放。
地图包含具有某些X和Y位置的占位符,我需要将list_items放在这些占位符后面。为此,我创建了目标表,其中包含随机放置在占位符后面的list_items。
下面是我能够将用户的list_items转储到目标表中的查询,但现在的问题是如何从source2表中为每个list_items随机获取X和Y位置。
INSERT INTO player_list_items
(player_list_list_id, player_list_player_id, player_list_item_id, player_list_item_cellX, player_list_item_cellY)
SELECT li.list_item_list_id, 584488596, li.list_item_item_id, 2, 5
FROM list_items li
WHERE li.list_item_list_id = 2
此后insert with multiple selects
或even another query {update}
对我有用,因为每个列表只会为用户运行一次。
每个列表包含多个项目,因此上面的查询返回多个项目并且工作正常,需要考虑的是map_details表还包含多个占位符,并且它们肯定会超过list_items的数量。
所需的查询应该从map_details表中获取所有位置X和Y,然后随机分配给每个项目,每个项目的位置必须是唯一的。
我见过多次选择插入的示例,但它们用于单行插入,我的问题是来自多个表的多行并且也是随机的。
I have a Stored Procedure for this case
因为它有很多其他的工作正常,所以,如果这里的任何人想要使用SP给出答案,这将是有用的,而不是我使用的问题。
希望上述内容有意义并澄清我的观点。
更新
我的第二个问题:
INSERT INTO player_list_items(player_list_list_id,player_list_player_id,player_list_item_id,player_list_item_cellX,player_list_item_cellY)
SELECT list_item_list_id, 584488596, list_item_item_id, game_map_details.cellX, game_map_details.cellY
FROM list_items
JOIN (SELECT * FROM game_map_details WHERE map_id = 1 ORDER BY RAND()) AS game_map_details
WHERE list_item_list_id = 2
GROUP BY list_item_item_id
这会添加map_details表中的数据,但数据不是随机的,实际上它只为list_items表中的所有4条记录插入1对记录
此致
答案 0 :(得分:0)
我不确定我是否关注,但听起来您需要将list_items
加入map_details
。如果两个表都有某种序列字段,它始终从1开始并且单调增加,没有间隙,则可以将它们连接起来。鉴于此数据:
Seq Name
1 Barrel
2 Box
3 Crate
Seq Position
1 13, 4
2 99, 2
3 8, 11
然后,SELECT I.Name AS ItemName, M.Position FROM Items AS I INNER JOIN Map AS M ON I.Seq = M.Seq
会给你这个:
ItemName Position
Barrel 13, 4
Box 99, 2
Crate 8, 11
虽然您可能有这样的字段,但由于您需要随机化,因此您需要在子查询中为两个表中的至少一个创建新序列;线程here讨论了如何在MySQL中这样做。在该线程中,行按特定顺序编号,但您可以按GUID或其他随机元素进行排序,以便以随机顺序获取项目。在MS SQL中,我使用ROW_NUMBER()
,而Oracle有ROWNUM
,但看起来MySQL可能不太方便。如果您找到了更好的方法,请将其添加到其他问题中,以造福子孙后代。
您需要将序列号乘以地图位置与项目数的比率,以便项目编号跨越整个地图编号范围。请务必将此比率计算为FLOAT
,但要将结果数字转换为INT
,以便正确加入。例如,如果有四个项目和十个地图位置,您将随机订购项目并为其分配数字1,2,3和4;将这些乘以2.5(地图位置与项目的比率),然后将它们舍入为整数,留下2(1 x 2.5,向下舍入为2),5,7和10.这不是完美的,因为这意味着一些地图位置会比其他位置更频繁地出现。如果您将地图位置''和''项目的顺序随机化,则它应该均匀。
以下是这可能如何运作的说明。假设您正在使用这些项目:
ItemID Name
42 Barrel
79 Box
101 Crate
...您正在使用这些地图位置:
MapID Location
22 13, 4
38 99, 2
44 8, 11
45 7, 10
首先为每个列表分配序号,如其他线程中所述:
ItemID Name Seq
42 Barrel 1
79 Box 2
101 Crate 3
MapID Location Seq
22 13, 4 1
38 99, 2 2
44 8, 11 3
45 7, 10 4
50 1, 12 5
您现在可以在Items.Seq = Map.Seq:
上将项目连接到地图ItemID Name Seq Location
42 Barrel 1 13, 4
79 Box 2 99, 2
101 Crate 3 8, 11
但是,您始终将项目分配给地图中的第一个元素。要解决此问题,您可以随机化地图元素的顺序,或者将项目的序列号乘以两个计数的比率(5/3):
ItemID Name Seq NewSeq
42 Barrel 1 1 * 1.6667 = 1.6667 = 1
79 Box 2 2 * 1.6667 = 3.3333 = 3
101 Crate 3 3 * 1.6667 = 5.0000 = 5
...现在,这些项目在地图位置之间均匀分布,分别为1,3和5,而不是在地图的开头聚集。请注意,如果项目列表和地图列表未更改,则每次项目仍将具有相同的位置,因此您可能最好将随机序列号分配给地图位置。
答案 1 :(得分:0)
好的,我得到了答案
使用了map_details的游标并循环通过它来更新项目列表,这里是代码,以防它帮助某人或某人给我一个更好的想法。
UPDATE player_list_items SET player_list_item_cellX = cell_X, player_list_item_cellY = cell_Y
WHERE player_list_id IN (
SELECT player_list_id FROM (
SELECT player_list_id FROM player_list_items
WHERE player_list_player_id = playerID AND player_list_list_id = @listID AND player_list_item_cellX IS NULL
ORDER BY player_list_id LIMIT 1
) tmp
);