Php 用于获取三个不同表比较的复杂mySQL查询

Php 用于获取三个不同表比较的复杂mySQL查询,php,mysql,sql,Php,Mysql,Sql,我需要创建非常困难的SQL查询,但我自己无法处理。也许有人可以帮助我或建议一些不同的方法。 我有三张桌子: 我需要在页面上显示需要以下几点的表格: 将每个用户点与管理员点进行比较(points.user\u id=1) 如果分数相等,则用户将根据分数保存日期和游戏举行日期之间的差异获得分数。如果点不同,则不添加点 我可以设置当上面提到的两个日期之间的差异为2天、3天等时,用户可以得到多少分(如果(games.date-points.date=2day{points=points*2}或类似)

我需要创建非常困难的SQL查询,但我自己无法处理。也许有人可以帮助我或建议一些不同的方法。

我有三张桌子:

我需要在页面上显示需要以下几点的表格:

  • 将每个用户点与管理员点进行比较(points.user\u id=1)
  • 如果分数相等,则用户将根据分数保存日期和游戏举行日期之间的差异获得分数。如果点不同,则不添加点
  • 我可以设置当上面提到的两个日期之间的差异为2天、3天等时,用户可以得到多少分(如果(games.date-points.date=2day{points=points*2}或类似)
  • 比较发生在(games.date>now()之后)
更新:

$points = array();

$all_ifo = mysql_query("SELECT p.id, p.user_id, p.game_id, p.points, 
ABS(p.points - a.points) rating_diff, a.points, g.home, g.datetime, u.username
FROM points AS p 
JOIN points AS a ON p.game_id = a.game_id AND a.user_id = 1
JOIN games  AS g ON p.game_id = g.id
JOIN users  AS u ON p.user_id = u.id
WHERE p.user_id != 1 AND g.datetime < NOW();") or die(mysql_error());

while ($info = mysql_fetch_assoc($all_ifo)){
    $points['' . $info['username'] . ''] += $info['rating_diff'];
    echo $info['p.id'];
}
asort($points);

echo "<table class='tabelid'><th>Test</th>";
foreach ($points as $key => $value) {
    $i++;
    echo "<tr><td>".$i.".</td><td style='width:250px;'>" . 
    ucfirst($key) . "</td><td>" . $value . "</td></tr>";
}
echo "</table>";
$points = array();

$all_ifo = mysql_query("SELECT x.*, d.*
  FROM Extra AS x
  JOIN (SELECT p.id, p.user_id, p.game_id, p.points, p.date, a.points adminpoints, g.home,
               g.datetime, u.username, TIMESTAMPDIFF(MINUTE, g.datetime, p.date) AS Offset
          FROM points AS p
          JOIN points AS a ON p.game_id = a.game_id AND a.user_id = 1
          JOIN games  AS g ON p.game_id = g.id
          JOIN users  AS u ON p.user_id = u.id
         WHERE p.user_id != 1
           AND g.datetime < NOW()
       ) AS d
    ON d.Offset >= x.LoOffsetFromGameTime
   AND d.Offset <  x.HiOffsetFromGameTime;") or die(mysql_error());

while ($info = mysql_fetch_assoc($all_ifo)){
    $points['' . $info['username'] . ''] += $info['Offset'];
    echo $info['p.id'];
    }

arsort($points);

echo "<table class='tabelid'><th>Test</th>";
foreach ($points as $key => $value) {
    $i++;
    echo "<tr><td>".$i.".</td><td style='width:250px;'>" . ucfirst($key) . "</td><td>" . $value . "</td></tr>";

}
echo "</table>";
那么,有什么建议应该如何做该表,以便在以后的系统中轻松实施?以及该评分如何获得正确的分值

更新3:

$points = array();

$all_ifo = mysql_query("SELECT p.id, p.user_id, p.game_id, p.points, 
ABS(p.points - a.points) rating_diff, a.points, g.home, g.datetime, u.username
FROM points AS p 
JOIN points AS a ON p.game_id = a.game_id AND a.user_id = 1
JOIN games  AS g ON p.game_id = g.id
JOIN users  AS u ON p.user_id = u.id
WHERE p.user_id != 1 AND g.datetime < NOW();") or die(mysql_error());

while ($info = mysql_fetch_assoc($all_ifo)){
    $points['' . $info['username'] . ''] += $info['rating_diff'];
    echo $info['p.id'];
}
asort($points);

echo "<table class='tabelid'><th>Test</th>";
foreach ($points as $key => $value) {
    $i++;
    echo "<tr><td>".$i.".</td><td style='width:250px;'>" . 
    ucfirst($key) . "</td><td>" . $value . "</td></tr>";
}
echo "</table>";
$points = array();

$all_ifo = mysql_query("SELECT x.*, d.*
  FROM Extra AS x
  JOIN (SELECT p.id, p.user_id, p.game_id, p.points, p.date, a.points adminpoints, g.home,
               g.datetime, u.username, TIMESTAMPDIFF(MINUTE, g.datetime, p.date) AS Offset
          FROM points AS p
          JOIN points AS a ON p.game_id = a.game_id AND a.user_id = 1
          JOIN games  AS g ON p.game_id = g.id
          JOIN users  AS u ON p.user_id = u.id
         WHERE p.user_id != 1
           AND g.datetime < NOW()
       ) AS d
    ON d.Offset >= x.LoOffsetFromGameTime
   AND d.Offset <  x.HiOffsetFromGameTime;") or die(mysql_error());

while ($info = mysql_fetch_assoc($all_ifo)){
    $points['' . $info['username'] . ''] += $info['Offset'];
    echo $info['p.id'];
    }

arsort($points);

echo "<table class='tabelid'><th>Test</th>";
foreach ($points as $key => $value) {
    $i++;
    echo "<tr><td>".$i.".</td><td style='width:250px;'>" . ucfirst($key) . "</td><td>" . $value . "</td></tr>";

}
echo "</table>";
但我不知道如何将其与额外的表进行比较,从而获得正确的分数。当然,只有当同一游戏id的分数(0、1或2)与管理员的分数(0、1或2)相同时,才应添加分数。

对SQL进行了小的调整 您当前的SQL(稍微重新格式化)是:

SELECT p.id, g.home, p.user_id, u.username, p.points, p1.points, 
       ABS(p.points - p1.points) rating_diff
FROM points p 
JOIN games g ON p.game_id = p.id
JOIN users u ON p.user_id = u.id
JOIN points p1 ON p.game_id = p1.game_id AND p1.user_id = 1
WHERE u.id != 1 
ORDER BY g.id, ABS(p.points - p1.points)
这应该接近你所追求的。你没有包括比赛日期标准。你说:

比较发生在
(games.date>now())
之后

这意味着比较是在未来游戏仍在计划中时进行的(因为游戏的时间戳在当前时间戳之后,通常称为“游戏发生之前”而不是“之后”。我假设您应该使用
而不是code>)

请注意,与您所拥有的相比,有一个直接的差异;因为我还没有从Users表中进行选择,所以必须将该条件从
u.id!=1
转换为
p.user\u id!=1
。这将继续。它不应该影响SQL的准确性,但TDQD已经给出了一个稍微不同的查询设计n

具有相应管理记录的非管理点记录: 同时选择游戏信息: (我很懒,没有把
datetime
放在后面的刻度中。)

仅选择历史游戏信息: 范围为“打开-关闭”;包括低值,排除高值。这意味着不能使用“与”运算符;它实现“打开-打开”范围,包括两个端点

“-99天”和“+99天”的值可以根据需要增加;天到分钟间隔的天部分的默认位数为2,但如果需要更多,可以指定更多位数。下面的查询假设游戏时间和进入时间之间的差始终正好在表中的一行中

还要选择额外的分数 假装我们可以使用此表,则额外点数的查询变为:

SELECT p.id, p.user_id, p.game_id, p.points, a.points, g.home, g.datetime, u.username
  FROM points AS p
  JOIN points AS a ON p.game_id = a.game_id AND a.user_id = 1
  JOIN games  AS g ON p.game_id = g.id
  JOIN users  AS u ON p.user_id = u.id
  JOIN extra  AS x
    ON CAST(g.datetime - p.date AS INTERVAL DAY TO MINUTE) >= x.LoOffsetFromGameTime
   AND CAST(g.datetime - p.date AS INTERVAL DAY TO MINUTE) <  x.HiOffsetFromGameTime
 WHERE p.user_id != 1
   AND g.datetime < NOW();

请将标题改为实际描述问题的内容。抱歉!很难命名。现在好点了吗?当然好点了,谢谢。:-)你是上帝!:)非常感谢!当然,我需要更多的帮助。我更新了我的问题,你能看一下吗!谢谢这是非常有教育意义的,我真的很感谢你的帮助,但你能看看我的更新3吗?我很快就能让它按我所希望的那样工作(当然是在你的帮助下)@Algeron:我已经添加了一点内容,我想,这可以解决你的遗留问题。看起来你从TIMESTAMPDIFF中得到了合理的数字,所以大部分的艰苦工作都是为我们完成的,这是函数的功劳。如果需要的话,你可以在额外的桌子上做TDQD,并且做一些简单的事情,指定游戏时间前后的不同分钟数,以检查你是否在给定的分钟数内看到额外的正确行。似乎我让我的系统工作了。我真是太感谢你了!:)但是在将来,如果我发现自己在SQL方面遇到了麻烦,我知道应该与谁联系!再一次谢谢
SELECT p.id, p.user_id, p.game_id, p.points
  FROM points AS p 
 WHERE p.user_id != 1;
SELECT p.id, p.user_id, p.game_id, p.points, a.user_id, a.points
  FROM points AS p
  JOIN points AS a ON p.game_id = a.game_id AND a.user_id = 1
 WHERE p.user_id != 1;
SELECT p.id, p.user_id, p.game_id, p.points, a.points, g.home, g.datetime
  FROM points AS p
  JOIN points AS a ON p.game_id = a.game_id AND a.user_id = 1
  JOIN games  AS g ON p.game_id = g.id
 WHERE p.user_id != 1;
SELECT p.id, p.user_id, p.game_id, p.points, a.points, g.home, g.datetime
  FROM points AS p
  JOIN points AS a ON p.game_id = a.game_id AND a.user_id = 1
  JOIN games  AS g ON p.game_id = g.id
 WHERE p.user_id != 1
   AND g.datetime < NOW();
SELECT p.id, p.user_id, p.game_id, p.points, a.points, g.home, g.datetime, u.username
  FROM points AS p
  JOIN points AS a ON p.game_id = a.game_id AND a.user_id = 1
  JOIN games  AS g ON p.game_id = g.id
  JOIN users  AS u ON p.user_id = u.id
 WHERE p.user_id != 1
   AND g.datetime < NOW();
CREATE TABLE Extra
(
    LoOffsetFromGameTime    INTERVAL DAY TO MINUTE NOT NULL,
    HiOffsetFromGameTime    INTERVAL DAY TO MINUTE NOT NULL,
    Points                  INTEGER NOT NULL,
    CHECK(LoOffsetFromGameTime < HiOffSetFromGameTime)
);

INSERT INTO Extra VALUES ('-99 23:59', '-0 00:45',  0);
INSERT INTO Extra VALUES ('-0 00:45',  '-0 00:24',  1);
INSERT INTO Extra VALUES ('-0 00:24',  '0 00:00',   2);
INSERT INTO Extra VALUES ('0 00:00',   '1 00:00',   4);
INSERT INTO Extra VALUES ('1 00:00',   '2 00:00',   6);
INSERT INTO Extra VALUES ('2 00:00',   '3 00:00',   8);
...
INSERT INTO Extra VALUES ('15 00:00',  '99 23:59', 34);
SELECT p.id, p.user_id, p.game_id, p.points, a.points, g.home, g.datetime, u.username
  FROM points AS p
  JOIN points AS a ON p.game_id = a.game_id AND a.user_id = 1
  JOIN games  AS g ON p.game_id = g.id
  JOIN users  AS u ON p.user_id = u.id
  JOIN extra  AS x
    ON CAST(g.datetime - p.date AS INTERVAL DAY TO MINUTE) >= x.LoOffsetFromGameTime
   AND CAST(g.datetime - p.date AS INTERVAL DAY TO MINUTE) <  x.HiOffsetFromGameTime
 WHERE p.user_id != 1
   AND g.datetime < NOW();
SELECT x.*, d.*
  FROM extra  AS x
  JOIN (SELECT p.id, p.user_id, p.game_id, p.usr_points, a.adm_points, g.home,
               g.datetime, u.username,
               CAST(g.datetime - NOW() AS INTERVAL DAY TO MINUTE) AS Offset
          FROM points AS p
          JOIN points AS a ON p.game_id = a.game_id AND a.user_id = 1
          JOIN games  AS g ON p.game_id = g.id
          JOIN users  AS u ON p.user_id = u.id
         WHERE p.user_id != 1
           AND g.datetime < NOW()
       ) AS d
    ON d.Offset >= x.LoOffsetFromGameTime
   AND d.Offset <  x.HiOffsetFromGameTime;
CREATE TABLE Extra
(
    LoOffsetFromGameTime    INTEGER NOT NULL,
    HiOffsetFromGameTime    INTEGER NOT NULL,
    Points                  INTEGER NOT NULL,
    CHECK(LoOffsetFromGameTime < HiOffSetFromGameTime)
);

INSERT INTO Extra VALUES (-2000000,      -45,  0);
INSERT INTO Extra VALUES (     -45,      -24,  1);
INSERT INTO Extra VALUES (     -24,        0,  2);
INSERT INTO Extra VALUES (       0,    +1440,  4);
INSERT INTO Extra VALUES (   +1440,    +2880,  6);
INSERT INTO Extra VALUES (   +2880,    +4320,  8);
...
INSERT INTO Extra VALUES (  +21600, +2000000, 34);
SELECT CASE WHEN d.usr_points = d.adm_points THEN x.points ELSE 0 END AS added_points,
       x.*, d.*
  FROM ...