使用多个表中的多个记录插入到表中

时间:2012-07-02 16:59:09

标签: mysql sql

我必须根据来自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 selectseven another query {update}对我有用,因为每个列表只会为用户运行一次。

每个列表包含多个项目,因此上面的查询返回多个项目并且工作正常,需要考虑的是map_details表还包含多个占位符,并且它们肯定会超过list_items的数量。

所需的查询应该从map_details表中获取所有位置X和Y,然后随机分配给每个项目,每个项目的位置必须是唯一的。

我见过多次选择插入的示例,但它们用于单行插入,我的问题是来自多个表的多行并且也是随机的。

I have a Stored Procedure for this case因为它有很多其他的工作正常,所以,如果这里的任何人想要使用SP给出答案,这将是有用的,而不是我使用的问题。

希望上述内容有意义并澄清我的观点。

enter image description here

更新

我的第二个问题:

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对记录

enter image description here

此致

2 个答案:

答案 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
             );