我的查询:
$units = DB::table('units')
->join('locations', 'locations.id', '=', 'units.location_id')
->join('castles', 'castles.id', '=', 'units.castle_id')
->join('unit_types', 'unit_types.id', '=', 'units.unit_type_id')
->select('units.location_id',
'units.previous_location_id',
'units.id as unit_id',
'units.castle_id',
'castles.guild_id',
'units.unit_type_id',
'units.current_health',
'unit_types.damage',
'unit_types.range')
->get()
->groupBy('location_id', 'castle_id');
会产生一些像这样的测试数据:
{
"1": [
{
"location_id": 1,
"previous_location_id": 1,
"unit_id": 2,
"castle_id": 1,
"guild_id": null,
"unit_type_id": 3,
"current_health": 90,
"damage": 10,
"range": 3
}
],
"2": {
"1": {
"location_id": 2,
"previous_location_id": 2,
"unit_id": 3,
"castle_id": 2,
"guild_id": null,
"unit_type_id": 5,
"current_health": 100,
"damage": 20,
"range": 2
},
"6": {
"location_id": 2,
"previous_location_id": 5,
"unit_id": 7,
"castle_id": 5,
"guild_id": null,
"unit_type_id": 15,
"current_health": 180,
"damage": 20,
"range": 3
}
},
"3": {
"2": {
"location_id": 3,
"previous_location_id": 3,
"unit_id": 4,
"castle_id": 3,
"guild_id": null,
"unit_type_id": 1,
"current_health": 100,
"damage": 10,
"range": 1
},
"3": {
"location_id": 3,
"previous_location_id": 3,
"unit_id": 5,
"castle_id": 3,
"guild_id": null,
"unit_type_id": 1,
"current_health": 100,
"damage": 10,
"range": 1
}
},
"4": {
"5": {
"location_id": 4,
"previous_location_id": 4,
"unit_id": 8,
"castle_id": 4,
"guild_id": null,
"unit_type_id": 20,
"current_health": 300,
"damage": 40,
"range": 2
},
"7": {
"location_id": 4,
"previous_location_id": 1,
"unit_id": 1,
"castle_id": 1,
"guild_id": null,
"unit_type_id": 1,
"current_health": 100,
"damage": 10,
"range": 1
}
},
"5": {
"4": {
"location_id": 5,
"previous_location_id": 5,
"unit_id": 6,
"castle_id": 5,
"guild_id": null,
"unit_type_id": 15,
"current_health": 180,
"damage": 20,
"range": 3
}
}
}
我正在尝试找到一种约束查询的方法,以便我只得到location_id
相同但castle_id
不同的结果,如下所示:
{
"2": {
"1": {
"location_id": 2,
"previous_location_id": 2,
"unit_id": 3,
"castle_id": 2,
"guild_id": null,
"unit_type_id": 5,
"current_health": 100,
"damage": 20,
"range": 2
},
"6": {
"location_id": 2,
"previous_location_id": 5,
"unit_id": 7,
"castle_id": 5,
"guild_id": null,
"unit_type_id": 15,
"current_health": 180,
"damage": 20,
"range": 3
}
},
"4": {
"5": {
"location_id": 4,
"previous_location_id": 4,
"unit_id": 8,
"castle_id": 4,
"guild_id": null,
"unit_type_id": 20,
"current_health": 300,
"damage": 40,
"range": 2
},
"7": {
"location_id": 4,
"previous_location_id": 1,
"unit_id": 1,
"castle_id": 1,
"guild_id": null,
"unit_type_id": 1,
"current_health": 100,
"damage": 10,
"range": 1
}
},
}
我尝试了类似->whereColumn('units.location_id', '<>', 'units.castle_id')
的内容,但在castle_id
碰巧有类似密钥的情况下无效。
修改的
这个原始SQL告诉我,当我在给定位置上有多个castle_id
时:
SELECT location_id,
COUNT(DISTINCT castle_id)
FROM units
GROUP BY location_id
ORDER BY COUNT DESC;
但我想直接选择这些行:
SELECT location_id,
FROM units
WHERE (DISTINCT castle_id);
编辑#2
这是一个假设:
units
有100行location_id: 1
location_id: 3
在包含location_id: 1
的10行中,所有10行也有castle_id: 76
在其中包含location_id: 3
13行的{20}行中有castle_id: 99
,其中7行有castle_id: 42
我正在尝试确定哪些行具有相同的location_id
,但castle_id
不相同。
在这种情况下,我会跳过10行,保留符合我标准的20行,然后检查剩余的70行。
编辑#3 这是一个要求的SQL小提琴:http://sqlfiddle.com/#!9/fad08
编辑#4 这是我的新查询:
$units = DB::table('units AS u1')
->select('u1.location_id',
'u1.previous_location_id',
'u1.id as unit_id',
'u1.castle_id',
'c1.guild_id',
'u1.unit_type_id',
'u1.current_health',
'ut.damage',
'ut.range')
->distinct()
->join('units AS u2', 'u1.location_id', '=', 'u2.location_id')
->join('castles AS c1', 'c1.id', '=', 'u1.castle_id')
->join('castles AS c2', 'c2.id', '=', 'u2.castle_id')
->join('unit_types AS ut', 'ut.id', '=', 'u1.unit_type_id')
->whereColumn([
['u1.castle_id', '<>', 'u2.castle_id'],
['c1.guild_id', '<>', 'c2.guild_id']
])
->orderBy('location_id')
->get();
echo $units;
基于fubar的答案,并在guild_id
相同时添加了另一个约束。
答案 0 :(得分:1)
此查询应该可以解决问题
SELECT id, location_id, castle_id FROM Units WHERE location_id IN (
SELECT a.location_id FROM Units a
JOIN Units b on (
b.location_id = a.location_id AND
b.castle_id <> a.castle_id
)
) ORDER BY location_id
答案 1 :(得分:0)
您可以使用以下查询实现所需目的:
SELECT DISTINCT u1.location_id, u1.previous_location_id, u1.id as unit_id, u1.castle_id, c.guild_id, u1.unit_type_id, u1.current_health, ut.damage, ut.srange
FROM units u1
INNER JOIN units u2 ON (u1.location_id = u2.location_id)
INNER JOIN castles c ON (c.id = u1.castle_id)
INNER JOIN unit_types ut ON (ut.id = u1.unit_type_id)
WHERE u1.castle_id <> u2.castle_id
ORDER BY u1.id
另见一个有效的SQL小提琴 - http://sqlfiddle.com/#!9/7c9cb8/3
至于使用Laravel Query Builder编写它,它看起来像:
$units = DB::table('units AS u1')
->select('u1.location_id', 'u1.previous_location_id', 'u1.id as unit_id', 'u1.castle_id', 'c.guild_id', 'u1.unit_type_id', 'u1.current_health', 'ut.damage', 'ut.range')
->distinct()
->join('units AS u2', 'u1.location_id', '=', 'u2.location_id')
->join('castles AS c', 'c.id', '=', 'u1.castle_id')
->join('unit_types AS ut', 'ut.id', '=', 'u1.unit_type_id')
->whereColumn('u1.castle_id', '<>', 'u2.castle_id')
->groupBy('u1.id')
->orderBy('u1.id')
->get();