Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 第二组中每个组的最大n个_Mysql_Greatest N Per Group - Fatal编程技术网

Mysql 第二组中每个组的最大n个

Mysql 第二组中每个组的最大n个,mysql,greatest-n-per-group,Mysql,Greatest N Per Group,我有一个数据库,其中每个条目都是一个带有源标记、关系和权重的边。我想执行一个查询,在给定一个源标记的情况下,我通过权重获得每个关系的前n条边 例如,给定条目 Id Source Relationship End Weight ----------------------------------------- 1 cat isA feline 56 2 cat isA animal 12 3

我有一个数据库,其中每个条目都是一个带有源标记、关系和权重的边。我想执行一个查询,在给定一个源标记的情况下,我通过权重获得每个关系的前n条边

例如,给定条目

Id   Source   Relationship   End      Weight
-----------------------------------------
1    cat       isA           feline   56
2    cat       isA           animal   12
3    cat       isA           pet      37
4    cat       desires       food     5
5    cat       desires       play     88
6    dog       isA           canine   72
如果我使用“cat”作为源进行查询,并且n=2,结果应该是

Id   Source   Relationship   End      Weight
-----------------------------------------
1    cat       isA           feline   56
3    cat       isA           pet      37
4    cat       desires       food     5
5    cat       desires       play     88
基于其他问题,我尝试了几种不同的方法

迄今为止最成功的是基于

因为边缘6对isA关系的权重高于边缘2,但由于source=“dog”


我对数据库非常陌生,所以如果我需要采取完全不同的方法,请告诉我。我不怕从头开始。

对相关子查询执行此操作确实效率低下,因为MySQL必须为外部查询的每一行运行子查询,只是为了确定外部查询中的行是否满足条件。那是一大笔开销

下面是一个不使用子查询的方法:

SELECT t1.*
FROM tablename t1
JOIN tablename t2 ON t1.source = t2.source and t1.relationship = t2.relationship
  AND t1.weight <= t2.weight
WHERE t1.source = 'cat' 
GROUP BY t1.id
HAVING COUNT(*) <= 2;
选择t1*
来自表名t1
在t1.source=t2.source和t1.relationship=t2.relationship上联接表名t2

t1.weight虽然效率不会太高,但MySQL允许您执行以下操作:

SELECT t1.*
FROM
  tablename t1 INNER JOIN (
    SELECT SUBSTRING_INDEX(
             GROUP_CONCAT(Id ORDER BY Weight DESC),
             ',',
             2) top_2
    FROM tablename
    WHERE Source='cat'
    GROUP BY Relationship) t2
  ON FIND_IN_SET(t1.id, t2.top_2);

请看小提琴。

这个很好用。快得多。最后一个问题,第二个代码建议是否有任何理由不能与mysqli一起使用?通过命令行直接与mysql一起使用时,我得到了107行,但通过mysqli使用时,只有28行。似乎
@n
需要初始化为非空值。我编辑了上面的内容来说明这一点。这样效果更好。对不起,我想我已经测试过了。
Id   Source   Relationship   End      Weight
-----------------------------------------
1    cat       isA           feline   56
4    cat       desires       food     5
5    cat       desires       play     88
SELECT t1.*
FROM tablename t1
JOIN tablename t2 ON t1.source = t2.source and t1.relationship = t2.relationship
  AND t1.weight <= t2.weight
WHERE t1.source = 'cat' 
GROUP BY t1.id
HAVING COUNT(*) <= 2;
SELECT *
FROM (
    SELECT tablename.*, IF(@r = relationship, @n:=@n+1, @n:=1) AS _n, 
        @r:=relationship AS _r
    FROM (SELECT @r:=null, @n:=1) _init, tablename
    WHERE source = 'cat'
    ORDER BY relationship, weight DESC
) AS _t
WHERE _n <= 2;
SELECT t1.*
FROM
  tablename t1 INNER JOIN (
    SELECT SUBSTRING_INDEX(
             GROUP_CONCAT(Id ORDER BY Weight DESC),
             ',',
             2) top_2
    FROM tablename
    WHERE Source='cat'
    GROUP BY Relationship) t2
  ON FIND_IN_SET(t1.id, t2.top_2);