J'aimerais trouver des couples d'articles dont l'écart price est inférieur à 5 $. Cela fonctionne avec:

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')

Comment obtenir une liste plate au lieu d'une liste de couples? c'est-à-dire:

(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  
2
Basj 17 avril 2018 à 00:45

3 réponses

Meilleure réponse

Tu peux faire:

select mt.*
from mytable mt
where exists (select 1 from mytable mt2 where abs(mt.price - mt2.price) < 5 and mt.id <> mt2.id);

Cependant, cela ne les organise pas dans un ordre particulier.

Si vous les voulez dans l'ordre, alors peut-être que le non-pivot est la meilleure option:

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;
1
Gordon Linoff 17 avril 2018 à 02:22

Au lieu de globaliser toutes les colonnes, essayez de spécifier vos noms de colonne:

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
0
thun 16 avril 2018 à 21:49

Vous pouvez créer une autre table pour savoir quelle table mt1 ou mt2 pour obtenir les valeurs. Cela sera également similaire à votre requête d'origine.

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;
0
âńōŋŷXmoůŜ 16 avril 2018 à 23:28