【问题标题】:MySQL groupwise maximumMySQL 分组最大值
【发布时间】:2018-12-04 19:54:31
【问题描述】:

编辑更新:原来我有 5.7 版,所以 Window Functions 不是找到解决方案的选项。

SHOW VARIABLES LIKE 'version';
+---------------+------------+
| Variable_name | Value      |
+---------------+------------+
| version       | 5.7.21-log |
+---------------+------------+

问题描述:我有一个offer、skills和profiles之间的三元关系表。这种三元关系有一个属性,排名。

我有一个技能表,我可以在其中看到技能的名称。到目前为止,我必须做两个查询:

1) 给我每个个人资料排名前 10 位的技能:

SELECT DISTINCT ternary.id_skill, skill.name_skill, ranking_skill
FROM ternary
INNER JOIN skill ON skill.id_skill=ternary.id_skill
WHERE ternary.id_perfil= #IntNumber#
GROUP BY ternary.id_skill
ORDER BY ternary.ranking_skill DESC
LIMIT 10;

2) 如需 ID 技能列表,请告诉我它们是否出现在任何个人资料中,以及它们出现的次数。

SELECT DISTINCT ternary.id_profile, nombre_profile, COUNT(DISTINCT ternary.id_skill) AS matching
FROM ternary
INNER JOIN profile ON ternary.id_profile=profile.id_profile
WHERE ternary.id_skill= '858534430'
  OR ternary.id_skill= '3213227'
  OR ternary.id_skill= '3254818'
GROUP BY(ternary.id_profile)
ORDER BY matching DESC;

在最后一个查询中发现了一个问题:它“搜索”出现在个人资料的任何位置的技能。由于个人资料可能拥有数千种技能,因此可能会产生误导,因为我们想要实现我现在只需要在它是任何个人资料的前 10 项技能之一时“搜索”。但只进入前 10 名。

到目前为止,基本上我一直在尝试混合两个查询,但收效甚微,因为似乎我无法在两列上进行分区,即使我只使用一列,我也会得到You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(PARTITION BY

SELECT *
FROM
(
   SELECT DISTINCT ternary.id_skill,
                   skill.name_skill,
                   ternary.ranking_skill,
                   ternary.id_profile,
                   ROW_NUMBER() OVER(PARTITION BY id_profile, id_skill ORDER BY ternary.ranking_skill DESC) rn
   FROM ternary
   INNER JOIN skill ON skill.id_skill=ternary.id_skill
)
WHERE rn < 11;

我了解到这个操作可能被称为分组最大值,我已经看到了几个寻找这个的答案。我无法复制它们中的任何一个,如果有任何帮助,我专门为mysql Ver 14.14 Distrib 5.5.60, for Linux (x86_64) using readline 5. 需要它(我已经尝试过对其他一些类似数据库来说非常完美但在 mysql 中不起作用的答案)。

表格定义:

CREATE TABLE `ternary` (
  `id_offer` varchar(200) NOT NULL,
  `id_skill` varchar(200) NOT NULL,
  `id_profile` varchar(200) NOT NULL,
  `ranking_skill` double NOT NULL,
  PRIMARY KEY (`id_offer`,`id_skill`,`id_profile`),
  KEY `id_skill` (`id_skill`),
  KEY `id_profile` (`id_profile`),
  CONSTRAINT `ternary_ibfk_1` FOREIGN KEY (`id_offer`) REFERENCES `offer` (`id_offer`),
  CONSTRAINT `ternary_ibfk_2` FOREIGN KEY (`id_skill`) REFERENCES `skill` (`id_skill`),
  CONSTRAINT `ternary_ibfk_3` FOREIGN KEY (`id_profile`) REFERENCES `profile` (`id_profile`)
)


CREATE TABLE `skill` (
  `id_skill` varchar(200) NOT NULL,
  `name_skill` varchar(200) DEFAULT NULL,
  `date` date DEFAULT NULL,
  PRIMARY KEY (`id_skill`)
  )

做的结果

select * from ternay limit 10;

+------------+------------+-----------+----------------------+
| id_oferta  | id_skill   | id_perfil | ranking_skill        |
+------------+------------+-----------+----------------------+
| 1004 | 107              | 679681082 |                    0 |
| 1004 | 115              | 679681082 |  0.10846866454897801 |
| 1004 | 117              | 679681082 | 0.038003619695992294 |
| 1004 | 129              | 679681082 |  0.04987975085098989 |
| 1004 | 147              | 679681082 |  0.02771097269499438 |
| 1004 | 299              | 679681082 |   0.0522549770819894 |
| 1004 | 321              | 679681082 |  0.11955305362697576 |
| 1004 | 417              | 679681082 |  0.11321911701097703 |
| 1004 | 964              | 679681082 | 0.015043099462996949 |
| 1004 | 967              | 679681082 |  0.05304671915898924 |
+------------+------------+-----------+----------------------+

查询 1) 的结果如上所述,它为我提供了 ONE 个人资料的前 10 名

+------------+--------------+---------------------+
| id_skill   | name_skill   | ranking_skill       |
+------------+--------------+---------------------+
| 109        | scala        |  0.3089840175329823 |
| 122        | hadoop       | 0.24164146109602963 |
| 9731       | python       | 0.21470443852124863 |
| 325        | java         | 0.18776741594646754 |
| 114        | sql          | 0.14736188208429596 |
| 101        | kafka        | 0.13389337079690544 |
| 301        | bbdd         | 0.13389337079690544 |
| 927        | agile        | 0.13389337079690544 |
| 320        | hive         |  0.1204248595095149 |
| 109        | spark        |  0.1204248595095149 |
+------------+--------------+---------------------+

【问题讨论】:

  • @LukaszSzozda 我明白了,所以如果解决方案需要,应该可以执行 OVER(Partition BY)。谢谢!
  • 您的 ROW_NUMBER 应仅按配置文件进行分区:ROW_NUMBER() OVER(PARTITION BY id_profile ORDER BY ternary.ranking_skill DESC)
  • @dnoeth 这两种方法我都试过了,都不行,我得到了同样的错误,这是一个语法错误,所以我写得不好
  • 那么你运行的不是 MySQL 8,而是以前的版本

标签: mysql sql groupwise-maximum


【解决方案1】:

这是一个示例,供您在没有 Window Functions 的情况下制作 Row_number(),您可以尝试在 select 子句上编写子查询。

  • PARTITION BY子查询where子句中的列写条件。
  • 子查询count(*) 使Row_number

看起来像这样。

SELECT * FROM 
(
SELECT *,(
     select (count(*) + 1) rn
     from ternary 
     where 
        t.id_profile = id_profile and 
        t.id_profile = id_profile and 
        ranking_skill > t.ranking_skill
   ) rn
  FROM ternary t
) t
WHERE rn < 11
order by rn 

sqlfiddle:http://sqlfiddle.com/#!9/7ee529/9

这个查询可能是可行的,你可以试试。

SELECT *
FROM
(
  SELECT DISTINCT t.id_skill,
                   skill.name_skill,
                   t.ranking_skill,
                   t.id_profile,
                   (
                     select (count(*) + 1) rn
                     from ternary 
                     where t.id_profile = id_profile and t.id_profile = id_profile
                     and ranking_skill > t.ranking_skill
                   ) rn
   FROM ternary t
   INNER JOIN skill ON skill.id_skill=t.id_skill;
)
WHERE rn < 11;

【讨论】:

    【解决方案2】:

    要加快您的第一次查询,请更改

    KEY `id_profile` (`id_profile`),
    

    KEY `id_profile` (`id_perfil`, id_skill, id_ranking),
    

    不要混用 DISTINCTGROUP BY。 (GroupBy 有效地做 Distinct。)

    nombre_profile 来自哪里? (当有悬空的列名时,很难提供帮助。)

    延迟获取skill.name_skill

    如果不使用ranking_skill,请不要将其从子查询中传递出去。

    JOIN 之一移动到子查询中。

    也许这具有正确组合两个查询的效果:

    SELECT  t.id_profile,
            nombre_profile,
            ( SELECT COUNT(DISTINCT id_skill)
                 FROM ternary
                 WHERE id_skill = ten.id_skill
            ) AS matching
        FROM  
            (  -- Get the 10 ids:
            SELECT  t.id_skill
                FROM  ternary AS t
                INNER JOIN  skill  ON skill.id_skill = t.id_skill
                WHERE  t.id_profile = #IntNumber#
                GROUP BY  t.id_skill
                ORDER BY  t.ranking_skill DESC
                LIMIT  10 
            ) AS ten
        INNER JOIN  profile AS p  ON t.id_profile = p.id_profile AS p
        GROUP BY(t.id_profile)
        ORDER BY  matching DESC;
    

    【讨论】:

    • 感谢您的回答!对于名称的更改,我感到很抱歉,我经常用我的语言编写变量,但是当我发布到 SO 时,我会努力翻译它们,以便更容易阅读。我没想到我犯了这么多错误,所以我很抱歉。
    猜你喜欢
    • 2011-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-19
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 2016-03-27
    相关资源
    最近更新 更多