【问题标题】:Is there a SQL technique for ordering by matching multiple criteria?是否有通过匹配多个条件进行排序的 SQL 技术?
【发布时间】:2011-03-10 21:11:15
【问题描述】:

我有几个表连接在一起形成一个包含列的表

designID
garmentID
colorID
sizeID
imageID

我有一个看起来像这样的函数[方括号中的变量是可选的]:

getProductImages($designID, [$garmentID], [$colorID], [$sizeID]);

我希望它按以下顺序返回与 $designID 匹配的所有 imageID:

  • 首先匹配 $garmentID、$colorID 和 $sizeID 的行
  • 下一个匹配 $garmentID 和 $colorID 的行
  • 下一个仅匹配 $garmentID 的行
  • 最后没有匹配的行(仅 $designID)

我可以很容易地做到这一点,只需加载与 $designID 匹配的所有行,然后在 PHP 中对它们进行排序,但我的理解是,如果可能的话,在 MySQL 中进行排序通常更快。将有大约 20 行与给定的 $designID 匹配。

所以我的问题是双重的:是否值得在 SQL 语句中进行排序?如果我这样做,最好的方法是什么?

我也很想知道这种排序是否有名称。

【问题讨论】:

    标签: php sql mysql sorting


    【解决方案1】:

    这是一个有趣的问题,阅读 Daniel 的回答教会了我一些(复杂的)我不知道的 SQL。

    然而,

    如果您只可能有 20 个这样的设计,那么现实情况是,排序在 php 或 MySQL 中会一样快。通常,除非您处理 1000 或数百万行,否则速度不是问题。

    【讨论】:

      【解决方案2】:

      如果我理解正确,您似乎可以在 ORDER BY 中使用表达式,其方式类似于以下 Stack Overflow 帖子中接受的答案:

      因此,您的查询可能如下所示:

      SELECT    imageID
      FROM      ...
      JOIN      ...
      WHERE     designID = 100          
      ORDER BY  garmentID = 1 DESC,
                colorID = 5 DESC,
                sizeID = 10 DESC;
      

      请注意,garmentIDcolorIDsizeID 不用作 WHERE 子句中的过滤器。这些值仅在 ORDER BY 表达式中使用。

      测试用例:

      CREATE TABLE designs (designID int, garmentID int, colorID int, sizeID int);
      
      INSERT INTO designs VALUES (100, 1, 1, 1);
      INSERT INTO designs VALUES (100, 1, 2, 2);
      INSERT INTO designs VALUES (100, 1, 5, 3);
      INSERT INTO designs VALUES (100, 1, 5, 10);
      INSERT INTO designs VALUES (100, 1, 5, 15);
      INSERT INTO designs VALUES (100, 1, 8, 20);
      INSERT INTO designs VALUES (100, 2, 5, 10);
      INSERT INTO designs VALUES (100, 2, 6, 15);
      INSERT INTO designs VALUES (101, 1, 1, 1);
      INSERT INTO designs VALUES (101, 2, 1, 1);
      

      结果:

      SELECT    * 
      FROM      designs 
      WHERE     designID = 100 
      ORDER BY  garmentID = 1 DESC, 
                colorID = 5 DESC, 
                sizeID = 10 DESC;
      
      +----------+-----------+---------+--------+
      | designID | garmentID | colorID | sizeID |
      +----------+-----------+---------+--------+
      |      100 |         1 |       5 |     10 |
      |      100 |         1 |       5 |      3 |
      |      100 |         1 |       5 |     15 |
      |      100 |         1 |       1 |      1 |
      |      100 |         1 |       2 |      2 |
      |      100 |         1 |       8 |     20 |
      |      100 |         2 |       5 |     10 |
      |      100 |         2 |       6 |     15 |
      +----------+-----------+---------+--------+
      8 rows in set (0.02 sec)
      

      注意与指定的garmentIDcolorIDsizeID 匹配的行如何排在第一位。否则,匹配 garmentIDcolorID 的行将是下一个。然后只匹配garmentID 的行跟随。然后剩下的,只匹配WHERE子句的designID过滤器。

      我相信在 SQL 中这样做是值得的。作为@Toby noted in the other answer,一般来说你不需要担心排序这么少的行时的性能,假设你总是按designID过滤... 至于你的其他问题,我不知道是否此类查询有一个名称 - 我倾向于将其称为“按表达式排序”。

      【讨论】:

      • 这项技术的一个重要免责声明是不匹配的列不会被排序;对于这个用例来说,这可能是也可能不是问题。
      • @Stobor:我想我不明白。你能举个例子吗?... 另请注意,我认为 OP 只需要结果集中的一列(imageId 列)。
      • 这正是我想要的,而且比我想象的要优雅得多。
      • 是的,我认为在这种情况下这没什么大不了的。我评论的是这样一个事实,即匹配 designID 和服装 ID 但在 sizeID 或 colorID 上不匹配的行将不会按 sizeID 或 colorID 排序。因此,例如,您的样本中的第 4、5 和 6 行可以按任何顺序返回。第 1 行保证排在第一位,然后是 2 和 3 以任意顺序排列,然后是 4、5 和 6 以任意顺序排列,然后是 7 和 8 以任意顺序排列。在某些情况下,这是相关的,在某些情况下你不在乎。
      猜你喜欢
      • 2017-05-21
      • 1970-01-01
      • 2011-04-13
      • 2013-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-17
      • 2019-01-28
      相关资源
      最近更新 更多