2016-05-25 15 views
0

私は上のMAXレベルとMINのレベルを取得しようとしていますfollowinMySQLのMAXとMIN

CREATE TABLE IF NOT EXISTS `players` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) NOT NULL, 
    `group_id` int(11) NOT NULL DEFAULT '1', 
    `account_id` int(11) NOT NULL DEFAULT '0', 
    `level` int(11) NOT NULL DEFAULT '1', 
    ... 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `name` (`name`), 
    FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE, 
    KEY `vocation` (`vocation`) 
) ENGINE=InnoDB; 

CREATE TABLE IF NOT EXISTS `guilds` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) NOT NULL, 
    `ownerid` int(11) NOT NULL, 
    `creationdata` int(11) NOT NULL, 
    `motd` varchar(255) NOT NULL DEFAULT '', 
    PRIMARY KEY (`id`), 
    UNIQUE KEY (`name`), 
    UNIQUE KEY (`ownerid`), 
    FOREIGN KEY (`ownerid`) REFERENCES `players`(`id`) ON DELETE CASCADE 
) ENGINE=InnoDB; 

CREATE TABLE IF NOT EXISTS `guild_membership` (
    `player_id` int(11) NOT NULL, 
    `guild_id` int(11) NOT NULL, 
    `rank_id` int(11) NOT NULL, 
    `nick` varchar(15) NOT NULL DEFAULT '', 
    PRIMARY KEY (`player_id`), 
    FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 
    FOREIGN KEY (`guild_id`) REFERENCES `guilds` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 
    FOREIGN KEY (`rank_id`) REFERENCES `guild_ranks` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB; 

ですプレイヤーテーブル1つのギルド内

は、しかし、私はいつもいつも最低レベル

をTISトップレベルと低レベルに同じ値を取得しています

は、私はあなたが

SELECT g.`id`, 
     g.`name`, 
     g.`ownerid`, 
     g.`creationdata`, 
     g.`motd`, 
     (SELECT Count(*) 
     FROM guild_membership a, 
       players_online b 
     WHERE a.player_id = b.player_id 
       AND a.guild_id = id) AS `online`, 
     (SELECT Max(b.level) 
     FROM players b join guild_membership a on a.player_id = b.id 
       AND a.guild_id = g.id) AS `toplevel`, 
     (SELECT Min(a.level) 
     FROM players a join 
       guild_membership b on a.id = b.player_id 
       AND b.guild_id = g.id) AS `lowlevel` 
FROM `guilds` g 
WHERE g.`name` = 'Wideswing Poleaxe' 
LIMIT 1; 

答えて

1

最初に気づくのは、LIMITORDER BYなしで使用していることです。だから、ギルドのテーブルからは、name = 'Wideswing Poleaxe'のエントリが複数あることが予想されますが、最初に見つかるDBMSを見てください。これが望ましいですか?

次は、日付が合わない結合構文です。どこからこれを取得しましたか? 20歳の本?あなたは、任意の修飾子なしidと比較して、そうしている:;-)明示的な使用は、あなたのサブクエリへと代わりに(JOIN ... ON ...

を結合してもそれ以上の年齢でなければならないのでありません、停止、20年前にこの構文はすでに、冗長化されましたDBMSはこれをguild_membership.idまたはplayers_online respにします。 、実際にはguild.idにします。 これは、予期しない値が得られることを説明します。

クエリの作成方法:集計されたプレーヤデータに代わりに参加できます。また、テーブルに一致するエイリアス名を使用します。あなたが任意のプレーヤーなしでギルドを確認する必要がない場合

select 
    guilds.id, 
    guilds.name, 
    guilds.ownerid, 
    guilds.creationdata, 
    guilds.motd, 
    players.online, 
    players.toplevel, 
    players.lowlevel 
from guilds 
left join 
(
    select 
    gms.guild_id, 
    max(p.level) as toplevel, 
    min(p.level) as lowlevel, 
    sum((select count(*) from players_online po where po.player_id = p.id)) as online 
    from guild_membership gms 
    join players p on p.id = gms.player_id 
    group by gms.guild_id 
) players on players.guild_id = guilds.id 
where guilds.name = 'Wideswing Poleaxe'; 

あなたは左の外側を変更することができますが、(join)に参加し、内側に(left join)に参加します。

+0

あなたの「オンライン」フィールドはたぶん1または0になります。すべてのプレーヤーが同時にオンラインまたはオフラインになっている場合、それらの値のうちの特定の値(同じデータ値セット上)が保証されます。 (つまり、サブクエリは必要ありません)。 – Uueerdo

+0

@Uueerdo:そうであれば、 'player'テーブルには単にオンラインでyes/noフラグを付けるか、もっと多くのデータには' id_player_online'フラグを設定する必要があります。しかし、逆の場合もあります。テーブル 'players_online'には' id_player'があります。したがって、1人のプレーヤーがそのテーブルで複数回使用できるようになります。だから、私のクエリはデータモデルにマッチしますが、もちろんそれはモデルの不具合かもしれません。 –

+0

私は、元の質問が 'players_online'テーブルをどのように使っているかを判断していました。あなたがそれを解釈していたとしても、元のクエリは、プレイヤーがオンラインになった総回数を取得するでしょう。いずれにせよ、あなたの 'online'値は、それが集計されていないか、またはそれが計算されたサブクエリを含むクエリによってグループ化されていないので、気まぐれになるでしょう。代わりに、そのギルドの実質的にランダムなプレイヤーがオンラインになった回数を取得します。 – Uueerdo

0

何であるかわからない私は、問題はここにあると思う:使用されてa.guild_id = id

IDは選手ではなく、ギルドからのもので、依然としてサブクエリの一部であるためです。

1

のようなあなたのクエリを変更することを検討してください間違っ

1

これらのサブクエリはすべて必要ではありません.JOINはほとんど常に高速で、通常は最初に試してみるべきです。唯一の非null値をカウント

SELECT `id`, `name`, `ownerid`, `creationdata`, `motd` 
     , COUNT(po.player_id) AS online 
     , MAX(p.level) AS toplevel 
     , MIN(p.level) AS lowlevel 
FROM `guilds` AS g 
LEFT JOIN guild_membership AS gm ON g.id = gm.guild_id 
LEFT JOIN players AS p ON gm.player_id = p.player_id 
LEFT JOIN players_online AS po ON gm.player_id = po.player_id 
WHERE g.`name` = 'Wideswing Poleaxe' 
; 

COUNT

これを試してみてください

...。同様に MAX, MINなどの他の集約関数は、NULL値を無視します(NULL値のみが処理された場合は、NULLを戻します)。