对于给定的唯一项目列表,在基于几列批量对它们进行排序后,我会得到重复的项目。
有2个表:
- item_popularity_tbl:
iid (UINT, PK) pplt (UTINYINT)
- item_cat_id_tbl:
iid (UINT, PK) cid (UTINYINT)
Where:
iid: item ID, unique values in the tables
cid: cat ID, values in the range (1, 15). Multiple items can have same cid.
pplt: popularity, vals in the range (1, 10). Multiple items can have same pplt.
给定一个项目ID列表,所有这些都是唯一的,我需要通过cid ASC然后pplt DESC来订购它。
我使用下面的SQL(使用MySQL)代码来实现它:
# python code snippet
def db_get_items_sorted(conn, iid_list, offset, limit):
n1 = ','.join( ['%s'] * len(iid_list) )
#
sql_stmt = ("SELECT a.iid, a.cid, b.pplt "
"FROM pclg.item_cat_id_tbl AS a "
"INNER JOIN pclg.item_popularity_tbl AS b ON b.iid=a.iid "
"WHERE a.iid IN (%s) "
"ORDER BY a.cid ASC, "
"b.pplt DESC "
"LIMIT %s,%s") % (n1, offset, limit)
#
return conn.query(sql_stmt % tuple(iid_list))
我以10个批次调用db_get_items_sorted(...)。我使用58个项目(唯一)的输入iid_list测试了这个,对照具有唯一iids的完全填充的表。对于每个调用,mysql根据请求返回具有适当排序的唯一10个iids。但是当我连接批次以创建最后58个项目时,我注意到列表中的几个项目(iid)是重复的(对于那些,返回的所有列都是相同的,基本上完全重复)。例如,48个唯一行和10个重复行。
如果我使用偏移0和限制58调用db_get_items_sorted(...),则没有iid重复。但是,我需要小批量打电话,因为我们可能会对未来几千个项目进行排序。
问题是:如何跨批次实现iid唯一性?
答案 0 :(得分:1)
您可以使用distinct进行查询,因此查询本身可以删除重复项。
sql_stmt = ("SELECT DISTINCT a.iid, a.cid, b.pplt "
"FROM pclg.item_cat_id_tbl AS a "
"INNER JOIN pclg.item_popularity_tbl AS b ON b.iid=a.iid "
"WHERE a.iid IN (%s) "
"ORDER BY a.cid ASC, "
"b.pplt DESC "
"LIMIT %s,%s") % (n1, offset, limit)
答案 1 :(得分:0)
我不想使用DISTINCT来解决问题。我不确定为什么行的重复首先发生,因此想要解决这个问题。
下面是使用ORDER BY:
中具有唯一值的列iid的修复 sql_stmt = ("SELECT a.iid, a.cid, b.pplt "
"FROM pclg.item_cat_id_tbl AS a "
"INNER JOIN pclg.item_popularity_tbl AS b ON b.iid=a.iid "
"WHERE a.iid IN (%s) "
"ORDER BY a.cid ASC, "
"b.pplt DESC, a.iid DESC "
"LIMIT %s,%s") % (n1, offset, limit)
TL; DR: 由于我们使用LIMIT和ORDER BY并且ORDER BY中使用的列没有唯一的val,因此发生了重复。
原因:
LIMIT会在找到满足查询所需的行数时返回。
当具有非唯一值的列与ORDER BY一起使用时,保持这些列的相同val的行不需要具有确定性排序。
因此,使用LIMIT并多次调用此例程(最终连接它们以产生最终结果),mysql运行ORDER BY几次,并且具有相同val的行(在ORDER BY中使用)是非有序的这些电话 - 即他们的立场不一致。然而,LIMIT M,N返回ORDER BY结果的特定(M,N)窗口中的行。
这导致最终的连接结果保留重复的行。
参考:https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html