Mysql 从两个表计算正确的计数
我很难选择正确数量的可见船只和物体。我将把模式分解为最少的信息,以避免问题过载。Mysql 从两个表计算正确的计数,mysql,Mysql,我很难选择正确数量的可见船只和物体。我将把模式分解为最少的信息,以避免问题过载。ships表最小化以显示所有示例数据 首先是我的模式和一个: 表船舶:如果船舶在船队中(fleetId>0),则当船队条目处理位置时,locationID设置为零。这些行没有在示例数据中列出,因为它们对解决方案没有用处(因为trex005有prooven-请参见他的答案) 表车队: +----------+---------+--------------+----------------+------------+
ships
表最小化以显示所有示例数据
首先是我的模式和一个:
表船舶
:如果船舶在船队中(fleetId>0
),则当船队条目处理位置时,locationID
设置为零。这些行没有在示例数据中列出,因为它们对解决方案没有用处(因为trex005有prooven-请参见他的答案)
表车队
:
+----------+---------+--------------+----------------+------------+
| fleetid | userid | numberTotal | numberVisible | locationId |
+----------+---------+--------------+----------------+------------+
| 1 | 1 | 5 | 5 | 666 |
| 2 | 1 | 5 | 0 | 666 |
| 3 | 1 | 5 | 3 | 666 |
| 4 | 2 | 2 | 2 | 666 |
| 5 | 3 | 10 | 0 | 666 |
| 6 | 4 | 2 | 0 | 666 |
| 7 | 5 | 2 | 0 | 666 |
+----------+---------+--------------+----------------+------------+
说明:
全局注意:即使测试数据没有显示:用户可以拥有船只或舰队,或者两者都有(在当前位置,这对我的问题来说不是必需的)
第一:ships表中的单个视图:一艘船可以是隐形的(isStealth=1
),也可以不是(isStealth=0
)。如果它是隐形的,则不应包括在计数中,如果用户将其视为任何正数量的可见船舶。但是如果一个用户没有可见的飞船,他应该被计算为1(用于攻击reasion)。对于给定的示例数据,可见船舶总数为:`4+2+1+1=8*:
- 用户1:有4个非隐形和1个隐形,使4个可见
- 用户2:有2个非隐形和0个隐形,使2可见
- 用户3:有0个非隐形和2个隐形,使1个可见
- 用户4:有1个非隐形和0个隐形,使1可见
第二:舰队表中的单个视图:在舰队中,它是类似的:numberVisible
显示该舰队的可见船只数量(对于所有者以外的其他用户),而numberTotal
包含该舰队中的全部船只数量。因此,如果舰队的numberTotal
大于其numberVisible
,这意味着舰队中有隐形船只。如果numberVisible
为零,则表示整个舰队包含隐身飞船,如果用户在轨道上至少有一艘**飞船或舰队*,则不可见,否则计数器中添加1。例如,给定船队可见船舶总数的数据为:8+2+1+1+1=13
- 用户1:拥有3支舰队,共15艘船。其中8个可见,7个不可见。数到8
- 用户2:拥有1个舰队,共2艘船。其中2个可见,0个不可见。数到2
- 用户3:拥有1个舰队,共有10艘船。其中0个可见,10个不可见。数一
- 用户4:拥有1个舰队,共2艘船。其中0个可见,2个不可见。数一
- 用户5:拥有1个舰队,共2艘船。其中0个可见,2个不可见。数一
第三:总数是这些数字的组合,同样有一条规则:如果用户至少有一艘可见的隐身舰,则忽略该值,否则将其视为一艘。
以示例数据为例,总计数为:`(12)+(4)+(1)+(1)+(1)=19*
- 用户1:有4艘可见船只和8艘舰队可见船只,总共12艘
- 用户2:有2艘可见船只和2艘舰队可见船只,总共4艘
- 用户3:拥有0艘可见船只和0艘舰队中的可见船只,总计1艘
- 用户4:舰队中有1艘可见船只和0艘可见船只,总共1艘
- 用户5:拥有0艘可见船只和0艘舰队中的可见船只,总计1艘
我的问题:
当前的遗留代码只是从MySQL中选择所有船只和舰队行,并将它们传递给PHP,在PHP中,在几个变量和if/else
语句的帮助下,在foreach
循环中计算数字。随着行数的增加(100k+),这会变得非常慢,我希望在一个查询中以最佳方式处理它。但这就是我挣扎的地方。
我成功地计算了舰队中的舰船和可见舰船的数量,但由于isStealth
attribute和用户的组合,我无法将隐身规则包括在其中
这就是我走了多远
select ((select count(shipid)
from ships
where locationId = 666
)
+
(select sum(numberVisible)
from fleets
where locationId = 666
)
) as visibleShips
这将返回总的10+10=20
,这说明是错误的。正如您所看到的,isStealth
attribute根本没有被使用。如果我将查询更改为
select ((select count(shipid)
from ships
where isStealth = 0
and locationId = 666
)
+
(select sum(numberVisible)
from fleets
where locationId = 666
)
) as visibleShips
总计数为7+10=17
,这也是错误的
然后我尝试使用fleetId
属性,但结果是45
select (select sum(if(s.fleetId > 0, f.numberVisible, 1))
from ships s
left join fleets f on (f.fleetId = s.fleetId)
where s.isStealth = 0
and (s.locationId = 666 or f.locationId = 666)
) as visibleShips
有人知道如何正确地将隐藏规则包括到查询中吗?使用两个IFs,您可以计算可见船只(如果它们存在,最小值为1)并将这些结果与可见舰队合并,然后为总数选择一个SUM()
SELECT
SUM(visibleTotal) as grandTotal
FROM
(
SELECT
userid,
SUM(visibleShips),
SUM(visibleFleetShips),
IF(SUM(visibleShips)+SUM(visibleFleetShips)=0,1,SUM(visibleShips)+SUM(visibleFleetShips)) as visibleTotal
FROM
(
(
SELECT
userid,
IF(totalShips - stealthShips > 0,totalShips - stealthShips,IF(stealthShips > 0,1,0)) as visibleShips,
0 as visibleFleetShips
FROM
(
SELECT
userid,
COUNT(shipid) as totalShips,
SUM(isStealth) as stealthShips
FROM ships
WHERE
locationId = 666
GROUP BY userid
) as foundShips
)
UNION
(
SELECT
userid,
0 as visibleShips,
SUM(numberVisible) as visibleFleetShips
FROM fleets
WHERE
locationId = 666
GROUP BY userid
)
) as userTotals
GROUP BY userid
) as grandTotals
我相信下面的代码应该可以工作,尽管它根本没有经过测试。语法也可能有点偏离,但想法是正确的
SELECT sum(iif (TEMP.sCount + TEMP2.fCount = 0, 1, TEMP.sCount + TEMP2.fCount))
FROM (SELECT Count(shipID) as sCount, userID
FROM Ships
WHERE isStealth = 0
AND LocationID = 666
GROUP BY userID) AS TEMP
INNER JOIN
(SELECT sum(numberVisible) as fCount, userID
FROM Fleets
WHERE locationID = 666
GROUP BY userID) as TEMP2
ON TEMP.userID = TEMP2.userID
如果有问题,请让我知道,但我们的想法是,您要跟踪每个用户进出船队的船舶数量,然后查看两者中可见的数量是否为0,如果是,则将其计算为1。希望这有帮助好吧,你失去了我。你能把你的问题简化成最简单的表达吗?@对不起,这是我得到的最详细的解释-我花了将近两个小时来写它,这样问题就清楚了,并给出了示例数据。trex005得到了-是的。这并没有给出预期的结果<如果用户没有船舶且只有没有可见船舶的船队(如用户5),则代码>总和(numberVisible)作为visibleFleetShips
不会返回1
。如果我将震源组子查询的选择更改为If(sum(numberVisible)>0,sum(numberVisible),1)作为visibleFleetShips
总数太高,因为没有可见船只的用户和没有可见船只的震源组被计数两次。你可以责备我
SELECT sum(iif (TEMP.sCount + TEMP2.fCount = 0, 1, TEMP.sCount + TEMP2.fCount))
FROM (SELECT Count(shipID) as sCount, userID
FROM Ships
WHERE isStealth = 0
AND LocationID = 666
GROUP BY userID) AS TEMP
INNER JOIN
(SELECT sum(numberVisible) as fCount, userID
FROM Fleets
WHERE locationID = 666
GROUP BY userID) as TEMP2
ON TEMP.userID = TEMP2.userID