我有一个充满了口袋妖怪卡片及其攻击的数据库。我想进行查询以找到每种类型攻击最强的神奇宝贝。我希望视图只显示攻击的名称,类型和损坏。
SELECT p2.MaxD, p2.Type, p1.name
FROM Pokemon p1
INNER JOIN ( SELECT type, MAX(damage) MaxD, pokemon_name FROM Attack GROUP BY Type )
p2 ON p1.type = p2.type AND p2.pokemon_name = p1.name
我有这个代码。它返回最高的伤害但不是正确的口袋妖怪。口袋妖怪表没有损坏字段。我正试着抓住连接。
这是结构:
攻击表有4个字段:pokemon_name(此攻击属于的口袋妖怪),伤害,名称(攻击名称)和类型(此攻击所属的口袋妖怪类型)。
宠物小精灵表有3:HP,类型(口袋妖怪)和名称(口袋妖怪)。
答案 0 :(得分:2)
首先,您必须构建选择,为每种类型选择最大伤害(您已经拥有):
SELECT type, MAX(damage) MaxD FROM Attack GROUP BY Type
现在,除非:
,否则效果不佳INT
(或ENUM
或其他数字类型)type
或type, damage
您无法选择pokemon_name
,因为MySQL不保证您会在stackoverflow上获得pokemon_name
匹配MaxD
(here's a nice answer已经涵盖此问题。)
现在您可以选择匹配pokemon_name
SELECT p1.pokemon_name, p1.type, p1.damage
FROM Attack p1
INNER JOIN (
SELECT type, MAX(damage) MaxD FROM Attack GROUP BY Type
) p2 ON p1.type = p2.type
AND p1.damage = p2.MaxDamage
GROUP BY (p1.type, p1.damage)
最后一个GROUP BY
声明确保拥有多个具有相同攻击力的小精灵不会导致一对type,damage
对的多条记录。
同样,将pokemon_name
替换为pokemon_id
,您将获得良好的效果。也许你应该谷歌database normalization
一段时间[wikipedia],[first tutorial]。您也可以查看this Q&A,它可以很好地概述“关系表”的含义。
现在你有正确的pokemon_name
(为了你的计划,我希望你用pokemon_id
替换它),你可以把它们放在一起:
SELECT p1.pokemon_name, p1.type, p1.damage, p.*
FROM Attack p1
INNER JOIN (
SELECT type, MAX(damage) MaxD FROM Attack GROUP BY Type
) p2 ON p1.type = p2.type
AND p1.damage = p2.MaxDamage
INNER JOIN Pokemon p
ON p.pokemon_name = p1.pokemon_name
GROUP BY (p1.type, p1.damage)
在完美的世界中,你的数据库看起来像这样:
-- Table with pokemons
CREATE TABLE `pokemons` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255),
-- More fields
PRIMARY KEY (`id`)
)
-- This contains pairs as (1,'Wather'), (2, 'Flame'), ...
CREATE TABLE `AttackTypes` (
`id`,
`name` VARCHAR(255)
)
-- Create records like (1, 2, 3, 152)
-- 1 = automatically generated keys
-- 2 = id of pokemon (let say it's Pikachu :P)
-- 3 = type of attack (this say it's Electric)
-- 152 = damage
-- This way each pokemon may have multiple attack types (Charizard flame + wind)
CREATE TABLE `Attacks` (
`id`,
`pokemonID` INT NOT NULL, -- Represents pokemons.id
`typeID` INT NOT NULL, -- Represents attack.id
`damage` INT
)
在此示例中 ID字段始终 PRIMARY KEY
,NOT NULL
和AUTO_INCREMENT
从中选择,再次获得类型:
SELECT MAX(attack.damage) AS mDmg, attack.typeID
FROM attack
GROUP BY attack.typeID
比得到口袋妖怪ID:
SELECT a.pokemonID, a.damage, a.typeID
FROM attack AS a
INNER JOIN (
SELECT MAX(a.damage) AS mDmg, a.typeID
FROM attack AS a
GROUP BY a.typeID
) AS maxA
ON a.typeID = maxA.typeID
AND a.damage = mDmg
GROUP BY (a.typeID)
一旦你覆盖了所有这些,你实际上可以选择口袋妖怪数据
SELECT aMax.pokemonID as id,
aMax.damage,
p.name AS pokemonName,
aMax.typeID AS attackTypeID,
t.name AS attackType
FROM (
SELECT a.pokemonID, a.damage, a.type
FROM attack AS a
INNER JOIN (
SELECT MAX(a.damage) AS mDmg, a.type
FROM attack AS a
GROUP BY a.type
) AS maxA
ON a.type = maxA.type
AND a.damage = mDmg
GROUP BY (a.type)
) AS aMax
INNER JOIN pokemons AS p
ON p.id = aMax.pokemonID
INNER JOIN AttackTypes AS t
ON t.id = aMax.typeID
MaxDamage
添加到AttackTypes
(将通过存储过程计算),并为您节省一个级别的空闲查询ID
字段都应为PRIMARY KEY
s Attacks.typeID
上的索引可让您快速获得所有能够进行此类攻击的小宠物Attack.damage
上的索引可让您快速找到最强攻击Attack.type, Attack.damage
(两个字段)上的索引在查找每次攻击的最大值时会很有帮助Attack.pokemonID
上的索引会更快地查找pokemon -> attack -> attack type name
答案 1 :(得分:1)
我不确定您的架构,但我认为pokemon_name
表的attack
实际上是口袋妖怪的名称。
SELECT a.*, c.*
FROM Attack a
INNER JOIN
(
SELECT type, MAX(damage) MaxD
FROM Attack
GROUP BY Type
) b ON a.Type = b.Type AND
a.damage = b.MaxD
INNER JOIN Pokemon c
ON c.Name = a.pokemon_name AND
c.Type = a.Type
以上查询显示attack
表和pokemon
表中的所有字段,但如果您对name
,damage
和type
真的感兴趣,你只对attack
表
SELECT a.*
FROM Attack a
INNER JOIN
(
SELECT type, MAX(damage) MaxD
FROM Attack
GROUP BY Type
) b ON a.Type = b.Type AND
a.damage = b.MaxD