Подтвердить что ты не робот

SQL выбирает записи в другой таблице, связанные внешними ключами

Я изменил структуру моей базы данных, чтобы использовать PRIMARY и FOREIGN KEYs, чтобы связать записи в моих трех таблицах вместе, и у меня возникают проблемы с попыткой записать запросы для выбора данных в одной таблице с данными в другой таблице. Вот пример моих 3 операторов CREATE TABLE:

CREATE TABLE IF NOT EXISTS players (
    id INT(10) NOT NULL AUTO_INCREMENT,
    username VARCHAR(16) NOT NULL, 
    uuid VARCHAR(200) NOT NULL DEFAULT 0,
    joined TIMESTAMP DEFAULT 0,
    last_seen TIMESTAMP DEFAULT 0,
    PRIMARY KEY (id)
);

/*      ^
    One |
       To
        | One
        v
*/

CREATE TABLE IF NOT EXISTS accounts (
    id INT(10) NOT NULL AUTO_INCREMENT,
    account_id INT(10) NOT NULL,
    pass_hash VARCHAR(200) NOT NULL, 
    pass_salt VARCHAR(200) NOT NULL, 
    created BIGINT DEFAULT 0,
    last_log_on BIGINT DEFAULT 0,
    PRIMARY KEY (id),
    FOREIGN KEY (account_id) REFERENCES players(id) ON DELETE CASCADE
) ENGINE=InnoDB;

/*      ^
    One |
       To
        | Many
        v
*/

CREATE TABLE IF NOT EXISTS purchases (
    id INT(10) NOT NULL AUTO_INCREMENT,
    account_id INT(10) NOT NULL,
    status VARCHAR(20) NOT NULL, 
    item INT NOT NULL, 
    price DOUBLE DEFAULT 0,
    description VARCHAR(200) NOT NULL,
    buyer_name VARCHAR(200) NOT NULL,
    buyer_email VARCHAR(200) NOT NULL,
    transaction_id VARCHAR(200) NOT NULL,
    payment_type VARCHAR(20) NOT NULL,
    PRIMARY KEY (id),
    FOREIGN KEY (account_id) REFERENCES accounts(account_id) ON DELETE CASCADE
) ENGINE=InnoDB;

Скажем, например, я хочу выбрать все имена пользователей, которые приобрели что-либо большее, чем 30 долларов. Все имена пользователей хранятся в таблице игроков, которая привязана к таблице учетных записей и привязана к таблице покупок. Это лучший способ создать эту реляционную базу данных? Если да, как бы я запускал запросы, подобные приведенному выше примеру?

Мне удалось получить всю историю покупок пользователей, учитывая их имя пользователя, но я сделал это с двумя подзапросами... Получение этих данных должно быть проще! Вот запрос SELECT, который я выполнил, чтобы получить все данные о покупке игроков:

SELECT * 
FROM purchases
WHERE account_id = (SELECT id FROM accounts WHERE account_id = (SELECT id FROM players WHERE username = 'username'));

Кроме того, когда я пытаюсь сделать ссылки на другие таблицы, используя что-то вроде "players.username", я получаю сообщение об ошибке, что столбец не существует...

Я ценю любую помощь! Спасибо!

4b9b3361

Ответ 1

Ваш дизайн в порядке, на мой взгляд. Соотношение между игроками и аккаунтом - один-ко-многим, а не один-к-одному, так как вы можете иметь два кортежа, ссылающихся на одного игрока.

Я бы написал запрос, который вам нужен:

SELECT DISTINCT p.id, p.username
FROM players p INNER JOIN accounts a ON (p.id = a.account_id)
               INNER JOIN purchases pc ON (a.id = pc.account_id)
WHERE (pc.price > 30);

Как сказал Сэм, я добавил DISTINCT, чтобы избежать повторения идентификатора и имени пользователя в случае, если у пользователя несколько покупок. Обратите внимание на идентификатор здесь, чтобы избежать путаницы между повторяющимися именами пользователей.