我选择正确数量的可见船只和物体时遇到了麻烦。我将模式分解为最小的信息,以免重载问题。最小化ships
表以显示所有示例数据。
首先是我的架构和SQLfiddle:
表ships
:如果船只在船队(fleetId > 0
)中,则locationID
设置为零,因为车队入口处理该位置。这些行未在示例数据中列出,因为它们对解决方案没有用处(因为trex005已经开发了 - 请参阅他的答案)。
+---------+---------+------------+----------+------------+
| shipid | userid | isStealth | fleetId | locationId |
+---------+---------+------------+----------+------------+
| 1 | 1 | 0 | 0 | 666 |
| 2 | 1 | 0 | 0 | 666 |
| 3 | 1 | 0 | 0 | 666 |
| 4 | 1 | 0 | 0 | 666 |
| 5 | 1 | 1 | 0 | 666 |
| 6 | 2 | 0 | 0 | 666 |
| 7 | 2 | 0 | 0 | 666 |
| 8 | 3 | 1 | 0 | 666 |
| 9 | 3 | 1 | 0 | 666 |
| 10 | 4 | 0 | 0 | 666 |
+---------+---------+------------+----------+------------+
表fleets
:
+----------+---------+--------------+----------------+------------+
| 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 |
+----------+---------+--------------+----------------+------------+
描述:
Global Note:即使测试数据确实显示了它:用户可以有船只或船队,也可以两者都有(在当前位置,这对我的问题不是必需的)。
第一个:船舶表中的单个视图:船舶可以是可盗取的(isStealth = 1
)或不是(isStealth = 0
)。如果它是可剥离的,则如果用户为任何可见船只的正数,则不应将其包含在count
中。但是如果用户没有可见的船,他应该算作1(用于攻击反应)。对于给定的示例数据,可见船舶的总数为:“4 + 2 + 1 + 1 = 8 *:
第二个:车队表中的单个视图:在一个类似的车队中:numberVisible
显示可见船只的数量(对于此舰队的其他用户而言,numberTotal
包含其中的全部船只。因此,如果舰队的numberTotal
大于其numberVisible
,则意味着其中有潜行的船只。如果numberVisible
为零,则意味着整个舰队包含潜行船只,如果用户在轨道上至少有一艘其他**船或舰队*,则不可见,否则将1添加到柜台。例如,给定船队可见船舶总数的数据为:8 + 2 + 1 + 1 + 1 = 13
第三:总计数是这些的组合,同样符合以下规则:如果用户至少有一个可见的船只偷窃被忽略,否则他算作一。 采用示例数据总计数为:`(12)+(4)+(1)+(1)+(1)= 19 *
我的问题:
当前的遗留代码只是从 MySQL 中选择船只和船队的所有行,并在几个变量的帮助下,在foreach
循环中将它们传递给 PHP { {1}}语句计算数字。随着越来越多的行(从100k +开始),这变得非常慢,我想在单个查询中处理它作为最佳。但这是我奋斗的地方。
我成功地计算了舰队的船只和可见船只的数量,但由于if/else
attribut和用户的组合,我无法将隐身规则纳入其中。
这是我走了多远。
isStealth
这将返回总共select ((select count(shipid)
from ships
where locationId = 666
)
+
(select sum(numberVisible)
from fleets
where locationId = 666
)
) as visibleShips
,这是错误的描述。如您所见,10 + 10 = 20
attribut根本没用过。如果我将查询更改为
isStealth
总计数为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
有没有人知道如何正确地将隐藏规则包含在查询中?
答案 0 :(得分:2)
我相信以下代码应该可行,但它根本没有经过测试。语法可能略有偏差,但这个想法很合理。
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.希望这有助于
答案 1 :(得分:1)
使用几个IF可以计算可见船只(如果它们有任何存在,则为1)UNION那些带有可见船队的结果,然后选择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