我有两张桌子:
Products
和SalesRecords
由此我可以创建一个简单的SQL语句来获得前100名最畅销的产品
SELECT p.item, p.price, COUNT(s.itemId)
FROM
SalesRecords s
LEFT JOIN Products p ON p.id=s.itemId
GROUP BY p.id
ORDER BY COUNT(s.itemId) DESC
LIMIT 100
(顺便说一句,我从SalesRecords中选择然后加入产品,因为我发现它比其他方式快得多 - 我想知道原因,但这不是主要问题!)
希望数据库模式足够清楚,知道发生了什么。我们在ID
中有Products
列与itemId
中的SalesRecords
列相关联,加入这些关系的表格,然后按每个产品行出现的次数排序SalesRecords。
我现在想要做的是按价格重新排序该列表并将其拆分为三个部分,然后从三个部分中的每一部分中随机返回两行。
预期结果是:
因此,从最畅销的产品中返回一个好的,更好的,最佳的产品建议。
(在实践中会有其他WHERE clasues等使这更相关,但查询的基础是我需要的)
这可能与SQL有关吗? (MySQL的)
答案 0 :(得分:0)
我不确定我能得到你想要的东西,但是。
这是你的sql with where子句而不是left join(我希望你没有null)
SELECT p.item, p.price, COUNT(s.itemId)
FROM SalesRecords AS s,Products AS p
WHERE p.id = s.itemid
GROUP BY p.id
ORDER BY COUNT(s.itemId) DESC
LIMIT 100
因此,上面的查询会返回一个您需要的表。但是您希望按价格排序。
SELECT p.item, p.price
FROM ( "put your above query here" )
ORDER BY p.price DESC
这将按价格对您的查询进行排序。
我认为我们应该为您的选择操作添加行号。
SET @rownumber := 1;
SELECT @rownumber := @rownumber + 1 AS rownum , p.item, p.price
FROM ( "put above query ordered by price" );
这将返回一个表,其中包含100行最佳商品,按价格和此列表的索引排序。现在我想,你想选择前2个最佳(索引1,2),2个中间(索引51,52)和2个底部(索引99,100)
SET @rownumber := 1;
SELECT @rownumber := @rownumber + 1 AS rownum , p.item, p.price
FROM ( "put above query ordered by price" );
WHERE rownum = 1 OR rownum = 2 OR rownum = 50 OR row num = 51 ....
这些查询效率非常低,可能会导致表崩溃。您可能想在您的数据库中创建一个WIEV,它是一个派生的虚拟表。这个新表将按行价指数(并经常更新)按价格订购最好的100个项目。如果你使用select itemid,其中rowindex是1,2,51,...在那个视图中,它会更安全。当然,只有在系统将来重载数据库时才会需要这个。
当您需要高级严格的mysql查询时,VIEW也可以非常方便地使用。
答案 1 :(得分:0)
您明确需要来自前三分之一,中间和底部三分之一的随机行。如果你没有100件商品会怎样?
开始的地方是计算实际返回的项目数量并计算它们。你可以用变量做到这一点。第一次传递后,变量@rn
将包含返回值的数量,因此此查询利用了该值。以下内容将价格组分配给每一行:
SELECT ps.*, floor((rn*3 - 1)/ @rn) as pricegroup
FROM (SELECT p.item, p.price, COUNT(s.itemId) as cnt, @rn := @rn + 1 as rn
FROM SalesRecords s LEFT JOIN
Products p
ON p.id=s.itemId CROSS JOIN
(select @rn := 0) const
GROUP BY p.id
ORDER BY COUNT(s.itemId) DESC
LIMIT 100
) ps;
接下来,您希望从每个中获取两个随机ID。这是MySQL的痛苦。以下是id
连接的方法:
SELECT floor((rn*3 - 1)/ @rn) as pricegroup,
substring_index(group_concat(p.item order by rand()), ',', 2) as randitems
FROM (SELECT p.item, p.price, COUNT(s.itemId) as cnt, @rn := @rn + 1 as rn
FROM SalesRecords s LEFT JOIN
Products p
ON p.id=s.itemId CROSS JOIN
(select @rn := 0) const
GROUP BY p.id
ORDER BY COUNT(s.itemId) DESC
LIMIT 100
) ps
GROUP BY floor((rn*3 - 1)/ @rn);
最后,我们可以加入回来获取更全面的信息:
SELECT p.*, pricegroup
FROM (SELECT floor((rn*3 - 1)/ @rn) as pricegroup,
substring_index(group_concat(p.item order by rand()), ',', 2) as randitems
FROM (SELECT p.item, p.price, COUNT(s.itemId) as cnt, @rn := @rn + 1 as rn
FROM SalesRecords s LEFT JOIN
Products p
ON p.id=s.itemId CROSS JOIN
(select @rn := 0) const
GROUP BY p.id
ORDER BY COUNT(s.itemId) DESC
LIMIT 100
) ps
GROUP BY floor((rn*3 - 1)/ @rn)
) pg join
products p
on find_in_set(p.item, pg.randitems);
不建议对大型数据执行这些操作。但是,您将数据限制为100行,因此性能应该非常合理。