如何编写"每组最大n"类型查询,但附加条件?

Nat*_*ate 5 mysql greatest-n-per-group

我问了一个关于昨天做出"每组最大n"类型查询的问题(当时不知道它被称为"每组最大n"),除了我问如何获得每组最少的.表结构如下:

type    name    value
=====================
1       item1    1
1       item2    20
2       item3    0
3       item4    5
3       item5    2
3       item6    50
Run Code Online (Sandbox Code Playgroud)

我收到了几个很好的答案,最有帮助的是:

SELECT t1.type, t1.name, t1.value
FROM mytable t1
LEFT JOIN mytable t2 ON t1.type = t2.type AND t1.value > t2.value
WHERE t2.value IS NULL
Run Code Online (Sandbox Code Playgroud)

以上查询结果如下:

type    name    value
=====================
2       item3    0
1       item1    1
3       item5    2
Run Code Online (Sandbox Code Playgroud)

然而,自从提出问题以来,我意识到我遗漏了一个重要的要求,我似乎无法弄清楚如何添加到上面的查询.我需要添加一个条件语句,而不是为每个组选择一个列值最小的行,而是为每个组选择一个列值最小的行,但是该行的另一个列的值大于某个列的值值.

这是我的新问题/问题:


我有下表(产品):

+-----------------------------------------------------------+
|   id   |   type   |   name   |   popularity   |   price   |
+-----------------------------------------------------------+
|    0   |    0     |   item1  |      3.5       |   0.99    |
|    3   |    1     |   item2  |      3         |   1.99    |
|    4   |    1     |   item3  |      6         |   2.95    |
|    6   |    1     |   item4  |      9         |   2.50    |
|    9   |    1     |   item5  |      12        |   3.75    |
|    12  |    2     |   item6  |      16        |   5.25    |
|    13  |    2     |   item7  |      32        |   10.95   |
|    14  |    2     |   item8  |      48        |   7.50    |
+-----------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

我需要在每个组中获得价格最低的项目(组是不同的类型值),其受欢迎程度大于某个数量(如果组中没有项目的人气超过指定数量,那么该组中没有项目应该退还).该句的最后一部分是这个问题与我上一个问题的不同之处.优选地,结果应按价格按升序排序.

所以,说流行度需要大于3,那么结果应该是:

+-----------------------------------------------------------+
|   id   |   type   |   name   |   popularity   |   price   |
+-----------------------------------------------------------+
|    0   |    0     |   item1  |      3.5       |   0.99    |
|    6   |    1     |   item4  |      9         |   2.50    |
|    12  |    2     |   item6  |      16        |   5.25    |
+-----------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

如果流行度需要大于6,那么结果应该是:

+-----------------------------------------------------------+
|   id   |   type   |   name   |   popularity   |   price   |
+-----------------------------------------------------------+
|    6   |    1     |   item4  |      9         |   2.50    |
|    12  |    2     |   item6  |      16        |   5.25    |
+-----------------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)

希望我能正确地完成这两个例子.无论如何,我认为你明白了.

是否可以在一个查询中执行我要求的操作?

TMS*_*TMS 4

这需要注意将条件放在哪里(towhere或 to on?),这样您就不会被欺骗:-) 您需要将 t1 的条件添加到where子句,并将 t2 的条件添加到on子句:

SELECT t1.type, t1.name, t1.value
FROM mytable t1
LEFT JOIN mytable t2 ON t1.type = t2.type AND t1.value > t2.value 
    AND t2.popularity > 3 /* here */
WHERE t2.value IS NULL 
    AND t1.popularity > 3 /* and here */
Run Code Online (Sandbox Code Playgroud)

还没有测试过,但应该可以。

尝试解释: where 子句中的条件会影响您将哪些元素视为具有最低值的潜在元素。而子句中的条件on会影响链接:您想要将其与其他哪些元素进行比较?它定义了您进行比较的组。从技术上讲,它会影响 t2.* 何时为 NULL。如果您将 t2.popularity 的条件指定为where子句,则对于最低元素受欢迎度较低的组,您将不会收到任何 NULL(即找不到具有最低值的元素)。