MySQL - 按category_id排序尽量避免重复彼此接近

时间:2015-04-15 15:24:58

标签: mysql sql-order-by

请忍受我的英语。

我有一张这样的表,

 id |  category_id  |  product_id
 -----------------------------------
  1 |  1            |  1
  2 |  1            |  2
  3 |  2            |  1
  4 |  2            |  3
  5 |  1            |  4
  6 |  3            |  5

我希望输出为

id  |  category_id  |  product_id
----------------------------------
1   |  1            |  1
3   |  2            |  1
6   |  3            |  5
2   |  1            |  2
4   |  2            |  3
5   |  1            |  4

因此,简而言之,我需要的是category_id必须按顺序排列,以便像1, 2, 3, 1, 2, 3,等等一样重复。

5 个答案:

答案 0 :(得分:19)

这是一个给你结果的查询:

SELECT p1.*
FROM `product` p1
JOIN `product` p2
      ON p2.category_id = p1.category_id 
      AND p2.id <= p1.id
GROUP BY p1.id
ORDER BY COUNT(*),category_id;

product是你的桌子。

请参阅DEMO HERE

答案 1 :(得分:5)

  

...尽量避免重复彼此接近

好吧,好的。我能提出的最简单的解决方案是GROUP BY 'product_id' ORDER BY 'category_id'。这会使你的表看起来像这样:

id  |  category_id  |  product_id
----------------------------------
1   |  1            |  1
3   |  2            |  1
2   |  1            |  2
4   |  2            |  3
5   |  1            |  4
6   |  3            |  5

我认为“必须对category_id进行排序以便它在循环中重复”是“我不希望彼此重复”的翻译。

如果您在产品1和产品2上有三个类别,它们将组合在一起(1,1,1,2,2,2),但类别将按数字顺序排列(1,2,3,1,2) ,3)。它不是你想要的完美解决方案,但它是一个简单的解决方案,似乎你给了你所需要的东西。

查询中任何复杂的hackery都只会降低查询速度。虽然现在可能不是问题,但如果你有很多记录,这可能是个大问题。

答案 2 :(得分:0)

这是我的解决方案:

SET @rank=-1;
SET @prior_category=null;
SELECT @cycle_length:=COUNT(distinct category_id) FROM table1;

SELECT id, category_id, product_id 
FROM 
     (SELECT @rank:=CASE WHEN @prior_category!=category_id THEN 0 ELSE @rank+1 END AS rank, @prior_category:=category_id AS prior_category_id, id, category_id, product_id 
      FROM table1 
      ORDER BY category_id) AS extended_table1
ORDER BY rank*@cycle_length + category_id, id;

在这里演示: http://sqlfiddle.com/#!9/5bce3/37

答案 3 :(得分:0)

//Get largest category_id value
$sql = "SELECT category_id FROM table ORDER BY category_id DESC LIMIT 1";
$result = $conn->query($sql);
$row = $result->fetch_assoc();
$maxCatId = $row['category_id'];

//Query for every possible category_id
$resultsArray = array();
for ($i = 1; $i <= $maxCatId; $i++) {
    $sql = "SELECT * FROM table WHERE category_id = " . $i;
    $resultsArray[] = $conn->query($sql);
}

//As long as $resultsArray is not empty
while ($resultsArray) {
    foreach ($resultsArray as $index => $res) {
        if ($row = $res->fetch_assoc()) {
            echo $row['id'] . ' ' . $row['category_id'] . ' ' . $row['product_id'];
        } else {
            unset($resultsArray[$index]);
        }
    }
}

首先获取category_id的最大值,然后从1循环到最大category_id并将所有结果对象存储在$resultsArray中。现在使用foreach一段时间输出结果。

foreach中的if else回显一条记录,或者如果结果对象中没有更多记录,则从$resultsArray中删除结果对象。当$resultsArray完全为空时,循环中断。

答案 4 :(得分:0)

你真的需要考虑重组你的表,你需要添加一个临时字段,将category_id分类,然后按该remp字段排序。 我的建议如下。

CREATE TABLE Test1     (id int,t_category int,category_id int,Product_id int) ;

INSERT INTO Test1     (idt_categorycategory_idproduct_id) VALUES     (1,1,1,1),         (2,2,1,2),         (3,1,2,1),         (4,2,2,3),     (5,3,1,4),     (6,1,3,5) ;

选择   CATEGORY_ID,   PRODUCT_ID 从   测试1   按t_category,category_id

排序