Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/67.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.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 从两个表计算正确的计数_Mysql - Fatal编程技术网

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