生气 - 我需要根据条件对分组结果进行排序

时间:2012-03-18 13:46:55

标签: mysql sql case greatest-n-per-group

我现在真的很挣扎,多年来一直在这上面,并且已经在这里问了两个问题!

所以,这是一个有希望更明确的问题。

我有一个包含数千种产品的产品数据库。

可以按item对产品进行分组,以免在搜索结果中显示多个基本相同但具有不同完成度的项目。

因此,简单的select查询将如下所示:

SELECT * FROM products GROUP BY item

这将为我提供所有产品,每个项目只显示一个(想法是观看客户点击其他内容以显示所有完成选项)

我可以使用类似

之类的东西来完成选项
SELECT *, GROUP_CONCAT(finishes) FROM products GROUP BY item

BUt ......这就是我遇到问题的地方

在我的搜索结果页面中,分组的“随机”顺序对我没有好处。我需要能够根据以下条件获得group子句中显示的项目

- If there is no stock of any finish, then display the cheapest option
- If there is stock, then display the cheapest item which is in stock

只获取一个ID并不好,我需要完整的记录,所以我需要的是一个条件语句来确定分组记录的显示顺序,以确保我从{{1获得的项目符合上述标准。

我根本无法弄清楚如何做到这一点,我已经尝试了数百万种不同的recordset和`CASE场景,但却无法让它发挥作用。

这是我今天早上到达的地方:

INNER JOIN

这是给我结果,但形式原因是某些项目被排除在结果之外,排序顺序仍然不正确。

要回答下面的@DRapp,这里有一些基本的样本数据

SELECT * FROM products prod INNER JOIN 
    (SELECT id, item, MIN(price) AS minPrice, totalStock, MAX(totalStock) AS maxStock,
    sum(totalStock) as sumTotalStock FROM products WHERE " & whereClause & "
GROUP BY item ORDER BY price) sortedProd ON 
    CASE WHEN sortedProd.sumTotalStock > 0 THEN " ' if there is some of this item in stock
        CASE WHEN sortedProd.minPrice = prod.price AND sortedProd.item = prod.item AND sortedProd.totalStock > 0 THEN  ' check if the item in stock is the cheapest
             sortedProd.minPrice = prod.price AND sortedProd.item = prod.item " ' if the cheapest one is ins tock, display it
        ELSE sortedProd.totalStock > 0  AND sortedProd.item = prod.item END" 'if not display whichever is in stock
    ELSE sortedProd.minPrice = prod.price AND sortedProd.item = prod.item END ' otherwise display the cheapest
GROUP BY prod.item ORDER BY prod.price DESC 

item      |    price     |     finish         | totalStock

item 1    |     £1       |       red          |     2
item 1    |     £1       |       blue         |     1
item 1    |     £1.50    |       blue & red   |     1

item 2    |     £2       |       red          |     0
item 2    |     £3       |       blue         |     1

item 3    |     £3.50    |       blue & red   |     1
item 3    |     £1       |       red          |     0
item 3    |     £2       |       blue         |     1

item 4    |     £4.50    |       blue & red   |     1

我希望看到的结果是:

  • 第1项,红色(sumTotalStock = 4) - '红色和蓝色都是最便宜的&有现货。显示的结果都很好,但要100%完美,显示红色,因为库存最大
  • 第2项,蓝色(sumTotalStock = 1) - '蓝色是唯一的库存
  • 第3项,蓝色(sumTotalStock = 2) - '显示蓝色,因为它最便宜库存
  • 第4项,蓝色&红色(sumTotalStock = 1) - 没有完成选项,所以无论库存/价格如何都只显示
  • 第5项,橙色(sumTotalStock = 0) - '没有库存,但显示橙色,因为它最便宜。

显然,实际显示的数据不仅仅是完成和价格,产品描述等,这可能会因完成而有所不同,因此我需要获得完整记录,但这个数据示例应该解释原理。

2 个答案:

答案 0 :(得分:0)

以下内容将为您提供最低价格的每件商品。您可以再次针对您的项目表加入此项以获取其余详细信息,加入项目和lowest_price。如果价格相等,你需要选择一种类型的制动器。这对你来说够了吗?

SELECT COALESCE(instock.price, allItems.price) as lowest_price, item FROM
(SELECT MIN(price) as minprice, item FROM products WHERE totalstock > 0 GROUP BY item) as instock
RIGHT OUTER JOIN
(SELECT MIN(price) as minprice, item FROM products GROUP BY item) as allItems
ON instock.item = allItems.item

编辑:MySQL没有完整的外部联接。更改为右外部联接,并从库存中删除条件,以便它具有所有项目。

答案 1 :(得分:0)

这应该使用"简单"左连接,没有嵌套选择;您的排序条件使查询看起来有点笨重:)

SELECT p1.*
FROM Products p1
LEFT JOIN Products p2
  ON p1.item=p2.item AND
     (IF(p1.totalstock,1,0) < IF(p2.totalstock,1,0) OR
      (IF(p1.totalstock,1,0) = IF(p2.totalstock,1,0) AND
       p1.price > p2.price) OR
      (p1.price = p2.price AND 
       p1.totalstock < p2.totalstock) OR
      (p1.price = p2.price AND 
       p1.totalstock = p2.totalstock AND
       p1.id > p2.id))
WHERE p2.id IS NULL

演示here