从两个表

时间:2015-08-03 13:27:43

标签: mysql

我选择正确数量的可见船只和物体时遇到了麻烦。我将模式分解为最小的信息,以免重载问题。最小化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 *:

  • 用户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是不可见的。计算1
  • 用户4:拥有1支舰队,共有2艘船。其中0是可见的,2是不可见的。计算1
  • 用户5:拥有1支舰队,总共2艘船。其中0是可见的,2是不可见的。计算1

第三计数是这些的组合,同样符合以下规则:如果用户至少有一个可见的船只偷窃被忽略,否则他算作一。 采用示例数据总计数为:`(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 中选择船只和船队的所有行,并在几个变量的帮助下,在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

有没有人知道如何正确地将隐藏规则包含在查询中?

2 个答案:

答案 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