Php 我如何进行此查询?
这是测试表Php 我如何进行此查询?,php,mysql,sql,Php,Mysql,Sql,这是测试表 ---------------------------------------------- id | username | point | level | created_date ---------------------------------------------- 1 | name_a | 1 | 1 | 2011-08-01 2 | name_a | 2 | 2 | 2011-08-02 3 | name_b | 5
----------------------------------------------
id | username | point | level | created_date
----------------------------------------------
1 | name_a | 1 | 1 | 2011-08-01
2 | name_a | 2 | 2 | 2011-08-02
3 | name_b | 5 | 1 | 2011-08-02
3 | name_c | 6 | 1 | 2011-08-02
4 | name_d | 1 | 1 | 2011-08-01
5 | name_d | 3 | 1 | 2011-08-02
5 | name_d | 5 | 2 | 2011-08-03
4 | name_e | 5 | 1 | 2011-08-01
5 | name_e | 5 | 2 | 2011-08-02
5 | name_e | 5 | 3 | 2011-08-03
----------------------------------------------
查询的要求是在一次查询中尽可能多地查询表的用户名和点
按每个级别的用户分数总和排序。
如果用户在同一级别上有两个分数,它将只获得最新的分数。
按用户名分组
总分必须小于10分
每个级别的最高分数为5分
输出样本:
--------------------
username | tpoint|
--------------------
name_d | 8 |
name_b | 5 |
name_a | 3 |
--------------------
name_e和name_c被忽略。听起来像是一个有趣的查询
SELECT username, SUM(point) AS points
FROM (SELECT username, level, point
FROM (SELECT username, level, LEAST(point, 5) AS point
FROM table
WHERE points <= 5
ORDER BY created_date DESC) AS h
GROUP BY username, level) AS h2
GROUP BY username
HAVING points < 10
ORDER BY points DESC
这应该够了!换张桌子就行了
编辑:
是否要排除得分超过5的行,或将值设置为5?只需删除其中的点
不知道我是否正确使用了别名,希望这能奏效
连接的内部查询是获取最新的用户名、级别组合,其中单个级别点计数大于5。然后,这将用于获得每个用户名的总积分,并丢弃分数超过10分的用户名。好的,先参加第2部分
SELECT *
FROM table a
WHERE NOT EXISTS (
SELECT 1
FROM table b
WHERE b.username=a.username
AND a.created_date>b.created_date
)
但是mysql不能很好地处理推送谓词,因此使用了max-concat技巧,但是这将使查询变得非常复杂——如果您遇到性能问题,那么值得重新访问。现在加入其他内容…第1、3和5部分
SELECT username, level, SUM(point)
FROM
(SELECT *
FROM table a
WHERE NOT EXISTS (
SELECT 1
FROM table b
WHERE b.username=a.username
AND a.created_date>b.created_date
)
) ilv
GROUP BY username, level
HAVING SUM(point) <= 5;
如何实现4取决于此约束相对于其他约束(特别是2和5)应用的确切顺序。以下应给出所述输入的disred输出
SELECT username, level, SUM(point)
FROM
(SELECT *
FROM table a
WHERE NOT EXISTS (
SELECT 1
FROM table b
WHERE b.username=a.username
AND a.created_date>b.created_date
)
) ilv,
(SELECT username, SUM(point) as totpoint
FROM table c
GROUP BY username
HAVING SUM(point)<=10) ilv2
WHERE ilv.username=ilv2.username
GROUP BY username, level
HAVING SUM(point) <= 5;
哎哟-再看一遍,你不想看到输出集中的级别细分-在这种情况下,Robin的答案更好。我认为这一点很接近,但你需要添加一个case语句来检查分数。它首先获取一个表,并对创建的日期进行排序。然后它根据用户名和级别进行分组,这将给point提供最新的值,按created_date DESC排序。您需要第二次选择吗?此外,仅在需要时使用select*。非常好!如果您在查询中发现任何其他值得更改的内容,请告诉我!:
SELECT
Query2.username
, Sum(Query2.SomVanpoint) AS point
FROM
(SELECT
test.username
, test.level
, Sum(test.point) AS SomVanpoint
FROM
test
INNER
JOIN
(SELECT
test.username
, test.level
, Max(test.created_date) AS MaxVancreated_date
FROM
test
GROUP
BY test.username
, test.level
) AS Query1
ON
(test.username = Query1.username)
AND (test.level = Query1.level)
AND (test.created_date = Query1.MaxVancreated_date)
GROUP
BY test.username
, test.level
HAVING
(((Sum(test.point))<= 5))
) AS Query2
GROUP
BY Query2.username
HAVING
(((Sum(Query2.SomVanpoint))< 10))
ORDER
BY Sum(Query2.SomVanpoint) DESC;
SELECT
Query2.username
, Sum(Query2.SomVanpoint) AS point
FROM
(SELECT
test.username
, test.level
, Sum(test.point) AS SomVanpoint
FROM
test
INNER
JOIN
(SELECT
test.username
, test.level
, Max(test.created_date) AS MaxVancreated_date
FROM
test
GROUP
BY test.username
, test.level
) AS Query1
ON
(test.username = Query1.username)
AND (test.level = Query1.level)
AND (test.created_date = Query1.MaxVancreated_date)
GROUP
BY test.username
, test.level
HAVING
(((Sum(test.point))<= 5))
) AS Query2
GROUP
BY Query2.username
HAVING
(((Sum(Query2.SomVanpoint))< 10))
ORDER
BY Sum(Query2.SomVanpoint) DESC;
username | point
----------+------
name_d | 8
name_b | 5
name_a | 3