Пересечение в sqlite3 в Python - PullRequest
2 голосов
/ 28 марта 2012

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

Это мои данные:

#(stock,price,recommendation)
my_data_1 = [('a',1,'BUY'),('b',2,'SELL'),('c',3,'HOLD'),('d',6,'BUY')]

#(stock,price,volume)
my_data_2 = [('a',1,5),('d',6,6),('e',2,7)]

Вот мои вопросы:

Вопрос 1:

Я пытаюсь извлечь цену, рекомендацию и объем, которые соответствуют активу «а».В идеале я хотел бы получить кортеж, подобный этому:

(u'a',1,u'BUY',5)

Вопрос 2:

Что если бы я хотел получить пересечение для всех акций (а не просто «а», как в вопросе 1), в данном случае это акции 'a' и акции 'd', тогда мой желаемый результат:

(u'a',1,u'BUY',5)
(u'd',6,u'BUY',6)

Как мне это сделать?

Вот моя попытка (Вопрос 1):

import sqlite3

my_data_1 = [('a',1,'BUY'),('b',2,'SELL'),('c',3,'HOLD'),('d',6,'BUY')]

my_data_2 = [('a',1,5),('d',6,6),('e',2,7)]

 #I am using :memory: because I want to experiment
 #with the database a lot

conn = sqlite3.connect(':memory:') 

c = conn.cursor()

c.execute('''CREATE TABLE MY_TABLE_1
          (stock TEXT, price REAL, recommendation TEXT )''' )

c.execute('''CREATE TABLE MY_TABLE_2
          (stock TEXT, price REAL, volume REAL )''' )



for ele in my_data_1:
    c.execute('''INSERT INTO MY_TABLE_1 VALUES(?,?,?)''',ele)

for ele in my_data_2:
    c.execute('''INSERT INTO MY_TABLE_2 VALUES(?,?,?)''',ele)    

conn.commit()

# The problem is with the following line:

c.execute( 'select* from my_table_1 where stock = ? INTERSECT select* from my_table_2 where stock = ?',('a','a')  )

for entry in c:
    print entry

Я не получаю ошибку, но также не выводить, поэтому что-то явно отключено.

Я также пробовал эту строку:

c.execute( 'select* from my_table_1 where stock = ? INTERSECT select volume from my_table_2 where stock = ?',('a','a') 

но это не работает, я получаю эту ошибку:

    c.execute( 'select* from my_table_1 where stock = ? INTERSECT select volume from my_table_2 where stock = ?',('a','a')  )
sqlite3.OperationalError: SELECTs to the left and right of INTERSECT do not have the same number of result columns

Я понимаю, почему у меня будет различное количество результирующих столбцов, но не совсем понимаю, почему это вызывает ошибку.

Как мне это сделать?

Заранее спасибо

Ответы [ 2 ]

5 голосов
/ 28 марта 2012

Похоже, что эти два вопроса на самом деле одинаковые.

Почему ваш запрос не работает: Давайте переформатируем запрос.

SELECT * FROM my_table_1 WHERE stock=?
INTERSECT
SELECT volume FROM my_table_2 WHERE stock=? 

Тамэто два запроса в пересечении,

  1. SELECT * FROM my_table_1 WHERE stock=?
  2. SELECT volume FROM my_table_2 WHERE stock=?

Значение "пересекаются" это "дать мне строки, которыев обоих запросах ".Это не имеет никакого смысла, если запросы имеют разное количество столбцов, поскольку невозможно, чтобы в обоих запросах появилась какая-либо строка.

Обратите внимание, что SELECT volume FROM my_table_2 не очень полезный запрос, посколькуне говорит вам, к какой акции принадлежит объем.Запрос даст вам что-то вроде {100, 15, 93, 42}.

Что вы на самом деле пытаетесь сделать: Вы хотите присоединиться.

SELECT my_table_1.stock, my_table_2.price, recommendation, volume
    FROM my_table_1
    INNER JOIN my_table_2 ON  my_table_1.stock=my_table_2.stock
    WHERE stock=?

Думайте о присоединении как«склейте строки из одной таблицы в строки из другой таблицы, предоставив данные из обеих таблиц в одну строку».

Странно, что цена появляется в обеих таблицах;когда вы пишете запрос с объединением, вы должны решить, хотите ли вы my_table_1.price или my_table_2.price или хотите присоединиться к my_table_1.price=my_table_2.price.Возможно, вы захотите изменить схему, чтобы этого не произошло, это может облегчить вашу жизнь.

2 голосов
/ 28 марта 2012

Вы страдаете от неправильного понимания того, как соотносить разные таблицы.

Чтобы сделать это, проще всего объединить их с подходящим условием, в результате чего результаты автоматически включают данные из обоихсоединенные столы.В приведенном ниже примере я выбираю все столбцы, но вы, конечно, можете выбрать только те, которые вам нужны, назвав их в предложении FROM.Вы также можете выбрать только те строки, которые вам нужны, с (a) дополнительными условиями в предложении WHERE.После того, как вы выполните свой код, попробуйте следующее:

>>> c.execute("select * from my_table_1 t1 JOIN my_table_2 t2 ON t1.stock=t2.stock")
<sqlite3.Cursor object at 0x1004608f0>

Это заставит SQLite взять строки из таблицы 1 и объединить их со строками таблицы 2, удовлетворяющими условиям в условии ON ( т.е. они должны иметь одинаковое значение для своего атрибута STOCK).Поскольку вы выбрали такие длинные имена таблиц, а я - дурацкая машинистка, я использовал таблицы alises в предложении FROM, чтобы позволить мне использовать сокращенные имена в остальной части запроса.

>>> c.fetchall()

затем дает вамрезультат

[(u'a', 1.0, u'BUY', u'a', 1.0, 5.0), (u'd', 6.0, u'BUY', u'd', 6.0, 6.0)]

, который, кажется, отвечает как 1), так и 2).Только для определенного значения STOCK просто добавьте

WHERE t1.STOCK = 'a'  -- or other required value, naturally

в строку запроса.Вы можете увидеть имена возвращаемых столбцов, запросив атрибут описания курсора:

>>> [d[0] for d in c.description]
['stock', 'price', 'recommendation', 'stock', 'price', 'volume']

Операция INTERSECT используется для получения выходных данных из двух отдельных запросов SELECT и возврата только тех элементов, которые встречаются в обоих.Я не думаю, что это будет полезно здесь.Причина, по которой вы получили ошибку, заключается в том, что запросы должны быть «совместимы с UNION», то есть им нужно одинаковое количество и тип столбцов в пересекающихся запросах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...