【问题标题】:How can I update the value of one field to the most often used value of another field?如何将一个字段的值更新为另一个字段最常用的值?
【发布时间】:2013-09-07 10:16:40
【问题描述】:

我有一个类似于以下的表格:

ID     收款人     类别
001  Costco      杂货店
002                                                                                                                                                                      糖果 003  Costco      维修
005  Costco      杂货店
006  好市多
007  好市多
008  See's

在没有编程语言帮助的情况下使用 MySQL,是否有一个查询(嵌套或不嵌套)可以将三个新行的类别设置为这些收款人最常用的类别?

例如,Costco 记录之一 (ID 003) 将 Repair 作为其类别,而其他两个 Costco 行 (ID 001 和 ID 005) 将 Grocery 作为其类别。因此,期望的结果是将新的 Costco 行(ID 006 和 ID 007)设置为 Grocery,因为这是该收款人最常用的类别。

【问题讨论】:

    标签: mysql sql-update


    【解决方案1】:

    当然.. 只需将 'your_table' 更改为您的表的名称

    UPDATE your_table
    LEFT JOIN (SELECT payee, category 
                 FROM
                 (SELECT payee, category FROM your_table WHERE category != '' AND category IS NOT NULL GROUP BY payee, category ORDER BY count(*) DESC) AS tbl2
                 GROUP BY payee
               ) AS tbl2 USING (payee)
    SET your_table.category = tbl2.category;
    

    这会将分类为维修的 costco 也更改为“杂货店”。如果您不想要这个,请添加:

      WHERE your_table.category IS NULL OR your_table.category = ''    
    

    到查询的最后

    【讨论】:

    • 感谢您的快速回复和解决方案。它绝对有效。一个问题。我将类别默认为空字符串,而不是空字符串。当我执行您的代码时,所有正确未更改的空类别值都更改为 null。有办法解决吗?再次感谢。
    • 通过将 WHERE 子句放在括号中并添加:AND tbl2.Category IS NOT NULL AND tbl2.Category != '' 解决了 null 问题
    • 抱歉昨天不在办公室,很高兴你解决了!
    【解决方案2】:

    这样就可以了

    UPDATE test t,
      (SELECT category,
              payee,
              count(*)
       FROM test ORDER BY count(*) desc LIMIT 1) t1
    SET t.category = t1.category
    WHERE t.payee = t1.payee
      AND (t.category = ''
           OR t.category IS NULL)
    

    Sqlfiddle http://www.sqlfiddle.com/#!2/ed5b0/1/0

    【讨论】:

      【解决方案3】:

      如果不重复创建派生表,我就是想不出办法:

      UPDATE t JOIN (
        SELECT s1.payee, s1.category FROM (
          SELECT payee, category, count(*) cat_count FROM t
          WHERE category IS NOT NULL
          GROUP BY payee, category
        ) s1
        LEFT JOIN (
          SELECT payee, category, count(*) cat_count FROM t
          WHERE category IS NOT NULL
          GROUP BY payee, category
        ) s2
        ON s1.payee = s2.payee AND s1.cat_count < s2.cat_count
        WHERE s2.cat_count IS NULL
      ) s
      ON t.payee = s.payee
      SET t.category = s.category
      WHERE t.category IS NULL;
      

      Fiddle here

      【讨论】:

        【解决方案4】:

        使用mysql的多表更新:

        UPDATE mytable t
        JOIN (SELECT payee, category
            FROM (SELECT payee, category
                FROM mytable
                GROUP BY 1, 2
                ORDER BY count(*) desc) x
            GROUP BY 1) y
            ON y.payee = t.payee
        SET t.category = y.category
        WHERE ifnull(t.category, '') = ''
        

        其中隐藏了一些功夫使它起作用:外部 group by 返回该组遇到的 first 行,这是由于最内部查询的排序将是计数最高的类别。

        【讨论】:

        • 问题是您不能依赖未使用 select 语句中的所有字段的组。 Documentation saysThe server is free to choose any value from each group。这意味着将为给定的收款人获取任何类别,不一定是first row encountered for the group
        • @MostyMostacho 是的,每个人都一直这么说,但实际上它在 100% 的情况下都有效。我挑战你创造一个不像我说的那样有效的例子。换句话说,我的代码可以通过任何测试——因为它总是可以工作——这使它成为定义好的代码。
        猜你喜欢
        • 2011-04-27
        • 1970-01-01
        • 2021-12-10
        相关资源
        最近更新 更多