我如何选择其中某些字段重复但其他字段在MySQL中进行比较的行

时间:2018-06-21 03:57:20

标签: mysql

我有1张桌子。 4个领域。如何找到在Species中具有重复值并且在Location中具有重复值的记录,并将Foo与其他记录中的Bar进行比较? (我正在寻找的Foo少于Bar

RecordId    Species   Location    Foo    Bar
1           Cat       home        4      9
2           Dog       home        4      9
3           Cat       home        3      7
4           Bunny     home        4      9
5           Cat       home        1      2

我想找到记录1和3。两者都具有Cat(在Species中)和home(在Location中),记录1中的Foo4,小于记录3中的Bar(即7)。记录5不匹配,因为记录1中的Foo不小于记录5中的Bar

如果我没有正确说出问题,请不要只是将其关闭。如果需要,我很乐意进行编辑。

1 个答案:

答案 0 :(得分:0)

让我们分解一下:

第1部分:在Field1Field2中共享重复值的记录:

这很简单。下面的查询返回在源表中多次出现的所有(Species + Location)元组。

SELECT
    Species,
    Location
FROM
    table
GROUP BY
    Species,
    Location
HAVING
    COUNT(*) > 1

这给出了以下结果:

Species   Location
Cat       home

然后,我们要获取具有这些已知重复值的原始原始记录(未分组的),我们可以通过在原始表上做一个INNER JOIN来做到这一点:

SELECT
    table.*
FROM
    table
    INNER JOIN
    (
        SELECT
            Species,
            Location
        FROM
            table
        GROUP BY
            Species,
            Location
        HAVING
            COUNT(*) > 1
    ) AS duplicates ON
        table.Species  = duplicates.Species AND
        table.Location = duplicates.Location

(将其作为WHERE子查询可能很诱人,但是灵活性较差,并且对问题的思考方式也不那么“关系”)

然后给出以下结果:

RecordId    Species   Location  Foo    Bar
1           Cat       home      4      9
3           Cat       home      3      7
5           Cat       home      1      2

第2部分:基于FooBar进行过滤:

这更复杂...这是您给的规则:

  • 记录1:之所以包含,是因为记录的Foo == 4小于记录3的Bar == 7
  • 记录3:除了满足重复条件的记录3外,您还没有解释为什么还要包括它?或者,当记录1的Bar = 7更高时,为什么还要使用记录3的Bar = 9与记录1进行比较。
  • 记录5:被排除,因为记录1的Foo == 4大于记录5的Bar == 2

我的解释是,每个组内(在这种情况下为记录1、3和5)仅返回Bar > MAX( Foo )处的记录。在这种情况下,MAX( Foo ) == 4包含了记录1和3,因为分别是9 > 47 > 4,而记录5和5不是因为2 > 4为假。

我们将从先前的查询中获取分组,并添加MAX聚合:

SELECT
    Species,
    Location,
    MAX( Foo ) AS MaxFoo
FROM
    table
GROUP BY
    Species,
    Location
HAVING
    COUNT(*) > 1

这给出了以下结果:

Species   Location    MaxFoo
Cat       home        4

(因为此查询是原始子查询的超集,所以我们不需要在第二个查询上JOIN,但是可以就地对其进行编辑):

SELECT
    table.*
FROM
    table
    INNER JOIN
    (
        SELECT
            Species,
            Location,
            MAX( Foo ) AS MaxFoo
        FROM
            table
        GROUP BY
            Species,
            Location
        HAVING
            COUNT(*) > 1
    ) AS duplicates ON
        table.Species  = duplicates.Species AND
        table.Location = duplicates.Location
WHERE
    table.Bar > duplicates.MaxFoo

此查询为您提供所需的结果:

RecordId    Species   Location  Foo    Bar
1           Cat       home      4      9
3           Cat       home      3      7

此查询还显示了对子查询执行JOIN而不是WHERE子查询的优势,因为您可以对数据执行更多操作(例如,如果要在输出中包含MaxFoo然后只需将SELECT table.* FROM...更改为SELECT table.*, duplicates.MaxFoo FROM...)。