2016-03-26 3 views
1

Я пытаюсь выполнить запрос к моей базе данных SQLite в Python в надежде вернуть результат в виде Pandas DataFrame. Однако в запросе что-то не так, что вызывает неправильный вывод со слишком большим количеством записей. Например, если я использую этот текст запроса:sqlite query с NATURAL JOIN производит дополнительные записи

query = "SELECT name, season, opponent, ratingA, ratingB 
    FROM players NATURAL JOIN games NATURAL JOIN A_ratings NATURAL JOIN B_ratings 
    WHERE (season="2015-16") AND (home_away="home") AND (tournament="tournX") AND (name="John Doe")" 

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

(u'John Doe', u'2015-16', u'TeamAlpha', 7.5, 8.0) 
(u'John Doe', u'2015-16', u'TeamBeta', 6.0, 6.0) 

Вместо, я получаю рейтинги для каждого игрока в команде для игр, которые соответствуют условиям, с именем из запроса, заменяющий правильное имя в name колонки, как это:

(u'John Doe', u'2015-16', u'TeamAlpha', 7.5, 8.0) 
(u'John Doe', u'2015-16', u'TeamAlpha', 8.5, 9.0) 
(u'John Doe', u'2015-16', u'TeamAlpha', 6.5, 7.0) 
(u'John Doe', u'2015-16', u'TeamAlpha', 6.5, 6.0) 
(u'John Doe', u'2015-16', u'TeamAlpha', 7.0, 7.0)) 
(u'John Doe', u'2015-16', u'TeamBeta', 6.0, 6.0) 
(u'John Doe', u'2015-16', u'TeamBeta', 8.0, 7.5) 
(u'John Doe', u'2015-16', u'TeamBeta', 7.0, 7.0) 
(u'John Doe', u'2015-16', u'TeamBeta', 7.5, 8.0) 
(u'John Doe', u'2015-16', u'TeamBeta', 6.5, 7.0) 

кажется, что есть какой-то умножение происходит между таблицами, и я думаю проблема в NATURAL JOIN часть, но Я не могу понять, как это исправить.

Я, конечно, новичок SQL, но я в тупике, потому что запрос работает отлично, если я ввожу его в свой DB-браузер для SQLite.

Таблицы структурированы следующим образом:

CREATE TABLE "games" (
`gameID` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, 
`season` TEXT, 
`tournament` TEXT, 
`home_away` TEXT, 
`opponent` TEXT, ) 

CREATE TABLE "players" (
`playerID` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, 
`name` TEXT UNIQUE) 

CREATE TABLE "A_ratings" (
`A_ratingID` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, 
`playerID` INTEGER, 
`gameID` INTEGER, 
`ratingA` REAL, 
FOREIGN KEY(`playerID`) REFERENCES `players`(`playerID`), 
FOREIGN KEY(`gameID`) REFERENCES games(gameID)) 

CREATE TABLE "B_ratings" (
`B_ratingID` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, 
`playerID` INTEGER, 
`gameID` INTEGER, 
`ratingB` REAL, 
FOREIGN KEY(`playerID`) REFERENCES `players`(`playerID`), 
FOREIGN KEY(`gameID`) REFERENCES games(gameID)) 

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

cnxn = sqlite3.connect(path) 
df = pd.read_sql(query, cnxn) 

ответ

2

Я предлагаю держаться подальше от естественных объединений и явно присоединяться к столбцам, к которым вы хотите присоединиться. Это берет догадки из вещей. Особенно в таком случае, когда это не четкое дело. У вас есть таблицы (игроки и игры), которые напрямую не связаны с ними, поэтому между этими двумя таблицами нет естественного соединения без привлечения таблиц рейтингов. В зависимости от порядка выполнения этих объединений вы можете получить перекрестное соединение (умножение). Небольшое дополнение к усложнению заключается в том, что и A_rating, и B_rating имеют свои собственные объединения для игр и игроков.

Не видя больше данных, я вроде угадывания основан на том, что вы получаете желаемые результаты в одном случае из естественных соединений, я бы дать что-то вроде этого попробовать:

query = """SELECT 
       name, season, opponent, ratingA, ratingB 
      FROM players 
       inner join A_ratings on 
       players.playerID = A_ratings.playerID 
       inner join B_ratings on 
       A_ratings.playerID = B_ratings.playerID and A_ratings.gameID = B_ratings.gameID 
       inner join games on 
        B_ratings.gameID = games.gameID 
      WHERE (season='2015-16') AND 
       (home_away='home') AND 
       (tournament='tournX') AND 
       (name='John Doe')""" 
+0

Объединение будет проще писать с помощью USING. –

+0

Спасибо тонну. Я понятия не имел, что имеет значение порядок объединений; Я думаю, именно поэтому мои попытки решения ломают меня. – jdep