从一对行的列表到一个平面的行列表
From a list of couples of rows to a flat list of rows
我想找到一些 price
相差小于 5 美元的商品。适用于:
import sqlite3
db = sqlite3.connect(':memory:')
c = db.cursor()
c.execute('CREATE TABLE mytable (id integer, price integer, name text)')
NAMES = ['Item A', 'Item B', 'Item C', 'Item D', 'Item E', 'Item F']
PRICES = [100, 101, 102, 189, 190, 229]
for i in range(len(NAMES)):
c.execute('INSERT INTO mytable VALUES (?, ?, ?)', (i, PRICES[i], NAMES[i]))
c.execute('SELECT mt1.*, mt2.* FROM mytable mt1, mytable mt2 WHERE ABS(mt1.price - mt2.price) < 5 AND mt1.id < mt2.id')
for e in c.fetchall(): print e
(0, 100, u'Item A', 1, 101, u'Item B')
(0, 100, u'Item A', 2, 102, u'Item C')
(1, 101, u'Item B', 2, 102, u'Item C')
(3, 189, u'Item D', 4, 190, u'Item E')
如何获得平面列表而不是情侣列表? 即:
(0, 100, u'Item A') # 1st item of couple #1
(1, 101, u'Item B') # 2nd item of couple #1
(0, 100, u'Item A') # 1st item of couple #2
(2, 102, u'Item C') # 2nd item of couple #2
(1, 101, u'Item B') # 1st item of couple #3
(2, 102, u'Item C') # 2nd item of couple #3
(3, 189, u'Item D') # 1st item of couple #4
(4, 190, u'Item E') # 2nd item of couple #4
尝试指定您的列名称,而不是全局化所有列:
SELECT mt1.id, mt1.price, mt1.name,
mt2.id, mt2.price, mt2.name,
FROM mytable mt1, mytable mt2
WHERE ABS(mt1.price - mt2.price) < 5
AND mt1.id < mt2.id
你可以这样做:
select mt.*
from mytable mt
where exists (select 1 from mytable mt2 where abs(mt.price - mt2.price) < 5 and mt.id <> mt2.id);
不过,这并没有按任何特定顺序排列它们。
如果您确实希望它们按顺序排列,那么逆轴旋转也许是最好的选择:
SELECT (CASE WHEN n = 1 THEN mt1.id ELSE mt2.id END) as id,
(CASE WHEN n = 1 THEN mt1.price ELSE mt2.price END) as price,
(CASE WHEN n = 1 THEN mt1.name ELSE mt2.name END) as name
FROM mytable mt1 JOIN
mytable mt2
ON ABS(mt1.price - mt2.price) < 5 AND mt1.id < mt2.id CROSS JOIN
(SELECT 1 as n UNION ALL SELECT 2) n
ORDER BY mt1.id, mt2.id;
您可以创建另一个 table 以了解要获取值的 table mt1 或 mt2。这也将类似于您的原始查询。
SELECT (CASE WHEN tbl.col='mt1' THEN mt1.id ELSE mt2.id END) as id,
(CASE WHEN tbl.col='mt1' THEN mt1.price ELSE mt2.price END) as price,
(CASE WHEN tbl.col='mt1' THEN mt1.name ELSE mt2.name END) as name
FROM mytable mt1, mytable mt2,
(SELECT 'mt1' as col
UNION SELECT 'mt2' ) tbl
WHERE ABS(mt1.price-mt2.price) < 5
AND mt1.id < mt2.id
ORDER BY mt1.id, mt2.id;
我想找到一些 price
相差小于 5 美元的商品。适用于:
import sqlite3
db = sqlite3.connect(':memory:')
c = db.cursor()
c.execute('CREATE TABLE mytable (id integer, price integer, name text)')
NAMES = ['Item A', 'Item B', 'Item C', 'Item D', 'Item E', 'Item F']
PRICES = [100, 101, 102, 189, 190, 229]
for i in range(len(NAMES)):
c.execute('INSERT INTO mytable VALUES (?, ?, ?)', (i, PRICES[i], NAMES[i]))
c.execute('SELECT mt1.*, mt2.* FROM mytable mt1, mytable mt2 WHERE ABS(mt1.price - mt2.price) < 5 AND mt1.id < mt2.id')
for e in c.fetchall(): print e
(0, 100, u'Item A', 1, 101, u'Item B')
(0, 100, u'Item A', 2, 102, u'Item C')
(1, 101, u'Item B', 2, 102, u'Item C')
(3, 189, u'Item D', 4, 190, u'Item E')
如何获得平面列表而不是情侣列表? 即:
(0, 100, u'Item A') # 1st item of couple #1
(1, 101, u'Item B') # 2nd item of couple #1
(0, 100, u'Item A') # 1st item of couple #2
(2, 102, u'Item C') # 2nd item of couple #2
(1, 101, u'Item B') # 1st item of couple #3
(2, 102, u'Item C') # 2nd item of couple #3
(3, 189, u'Item D') # 1st item of couple #4
(4, 190, u'Item E') # 2nd item of couple #4
尝试指定您的列名称,而不是全局化所有列:
SELECT mt1.id, mt1.price, mt1.name,
mt2.id, mt2.price, mt2.name,
FROM mytable mt1, mytable mt2
WHERE ABS(mt1.price - mt2.price) < 5
AND mt1.id < mt2.id
你可以这样做:
select mt.*
from mytable mt
where exists (select 1 from mytable mt2 where abs(mt.price - mt2.price) < 5 and mt.id <> mt2.id);
不过,这并没有按任何特定顺序排列它们。
如果您确实希望它们按顺序排列,那么逆轴旋转也许是最好的选择:
SELECT (CASE WHEN n = 1 THEN mt1.id ELSE mt2.id END) as id,
(CASE WHEN n = 1 THEN mt1.price ELSE mt2.price END) as price,
(CASE WHEN n = 1 THEN mt1.name ELSE mt2.name END) as name
FROM mytable mt1 JOIN
mytable mt2
ON ABS(mt1.price - mt2.price) < 5 AND mt1.id < mt2.id CROSS JOIN
(SELECT 1 as n UNION ALL SELECT 2) n
ORDER BY mt1.id, mt2.id;
您可以创建另一个 table 以了解要获取值的 table mt1 或 mt2。这也将类似于您的原始查询。
SELECT (CASE WHEN tbl.col='mt1' THEN mt1.id ELSE mt2.id END) as id,
(CASE WHEN tbl.col='mt1' THEN mt1.price ELSE mt2.price END) as price,
(CASE WHEN tbl.col='mt1' THEN mt1.name ELSE mt2.name END) as name
FROM mytable mt1, mytable mt2,
(SELECT 'mt1' as col
UNION SELECT 'mt2' ) tbl
WHERE ABS(mt1.price-mt2.price) < 5
AND mt1.id < mt2.id
ORDER BY mt1.id, mt2.id;