2

我有一个 SQL 表,其中包含 1500 多个在线游戏的数据。这些游戏中的每一个都有描述它们的标签(每个游戏有 1 到 5 个标签)。例如,此游戏按重要性顺序具有以下标签“越野车”、“赛车”、“特技”、“试验”、“山”。对于这些游戏中的每一个,我想选择最相关的 12 款游戏。

我正在考虑为每个标签赋予“重要性顺序”权重。

标签 1 = 5 分

标签 2 = 4 分

标签 3 = 3 分

标签 4 = 2 分

标签 5 = 1 分

并乘以匹配的标签。因此,如果另一个游戏是关于“汽车”、“赛车”、“山地”的,它将得到:0 + (4 x 4) + (3 x 1) = 19 分。然后我会比较所有比赛的结果,并显示得分最高的 12 场比赛。

我知道如何使用 PHP 编写数学比较部分,但不知道如何在仅显示前 12 个游戏之前有效地存储部分结果(即每个 1500 的比较点)。我应该创建一个表来存储临时 1500 结果吗?或者有没有办法将这些结果存储在内存中,然后只抓取前 12 个?

注意:我可能会将最终结果存储在一个 1500x12 的 SQL 表中,并仅在我添加新游戏时运行比较,大约每天一次。

4

3 回答 3

2

虽然这个问题应该被认为太宽泛,不适合在这里(请在提问之前尝试一些东西!),这对我来说很有趣来回答它。

我不会在 PHP 中这样做,而是在纯 SQL 中这样做。

假设这样的结构:

CREATE TABLE game (
    game_id INT PRIMARY KEY,
    name VARCHAR(50)
);

CREATE TABLE tag (
    tag_id INT PRIMARY KEY,
    label VARCHAR (50)
);

CREATE TABLE gametag (
    game_id INT,
    tag_id INT,
    rank INT, -- ranks from 1 to 5, rank "1" will weightmeans "5 points"
    PRIMARY KEY (game_id, tag_id),
    UNIQUE (game_id, tag_id, rank),
    CONSTRAINT gid_fk FOREIGN KEY gid_fk_idx (game_id) REFERENCES game (game_id),
    CONSTRAINT tid_fk FOREIGN KEY tid_fk_idx (tag_id) REFERENCES tag (tag_id)
);

两个游戏之间的“匹配分数”将通过如下查询获得:

SELECT
    game1.name AS game_1,
    game2.name AS game_2,
    SUM(match_score) AS score
FROM (
    SELECT
        game1.game_id AS game1_id,
        game2.game_id AS game2_id,
        (6 - gametag1.rank) * (6 - gametag2.rank) AS match_score -- modify the magic "6" if you allow more or less than 5 tags
    FROM game AS game1
    JOIN gametag AS gametag1 USING (game_id)
    JOIN tag AS tag1 USING (tag_id)
    JOIN tag AS tag2 USING (tag_id)
    JOIN gametag AS gametag2 USING (tag_id)
    JOIN game AS game2 ON game2.game_id = gametag2.game_id
    WHERE game1.game_id = 1 AND game2.game_id = 2
) AS scores
JOIN game AS game1 ON game1.game_id = game1_id
JOIN game AS game2 ON game2.game_id = game2_id
GROUP BY game1_id, game2_id;
于 2013-06-05T16:35:05.853 回答
0

继承人一些 SQL,也许这会工作?:

SELECT g.id AS game_id, g.game AS game_name, SUM(t.tag_points) AS tag_points 
FROM games g
INNER JOIN game_tags gt 
    ON gt.game_id = g.id 
INNER JOIN tags t
    ON t.id = gt.tag_id
GROUP BY gt.game_id  
ORDER BY tag_points DESC

您将需要一个类似于此的表结构:

Table: games
+----+-------------+
| id | game        |
+----+-------------+
| 1  | Test Game 1 |
| 2  | Test Game 2 |
+----+-------------+

 Table: tags
+----+------------+------------+
| id | tag_name   | tag_points |
+----+------------+------------+
| 1  | test tag 1 | 1          |
| 2  | test tag 2 | 2          |
+----+------------+------------+

Table: game_tags
+----+---------+--------+
| id | game_id | tag_id |
+----+---------+--------+
| 1  | 1       | 1      |
| 2  | 2       | 1      |
| 3  | 2       | 2      |
+----+---------+--------+
于 2013-06-05T16:33:19.347 回答
0

桌子tags

id  |    name    |
------------------
 1  |    cars    |
 2  |    rpg     |
 3  |   shooter  |
 4  |  mountain  |
 5  |    fps     |
 6  |   trial    |
 7  |   racing   |
 8  |   ....     |
 9  |   ....     |

桌子games

id  |    name    |
------------------
 1  | race_game  |
 2  | shoot_game |

桌子game_tags

id  | game_id | first_tag | second_tag | third_tag | fourth_tag | fifth_tag | 
-----------------------------------------------------------------------------
1   |   1     |    7      |     1      |     4     |       2    |    6      |
2   |   2     |    5      |     8      |     3     |       2    |    9      |

因此,您可以多次左加入 game_tags 以比较第一次加入的标签在哪里等于第二次加入,依此类推。LEFT JOIN 会给你非匹配值的 NULL 结果,所以只有可匹配的才会有 tag_id。根据匹配的标签,您可以给出分数。例如,如果这里的匹配从第四个标签开始,你会给第四个标签的分数,据我了解,第一个标签匹配给更多的分数,并随着标签的排名而减少。

于 2013-06-05T16:45:48.203 回答