COALESCE在LEFT JOIN上返回非聚合异常

时间:2018-07-08 14:54:44

标签: mysql sql

我正在尝试下一场比赛周的比赛。游戏周是指比赛进行时,我们可以具有以下类型的游戏周:20、21、22、23。每个游戏周都播放到特定日期。现在所有的比赛都有特定的状态,如果状态值为5,我可以查看是否在特定游戏周的比赛中进行过比赛,否则,状态为:1、2、3、4。

主要问题和数据结构

主要问题:游戏周。我想返回已经进行的比赛的下一个比赛周,所以假设我有以下比赛:

| id | round.id | status | gameweek | date
  1      488        5         1        1/07/2018
  2      488        5         1        1/07/2018
  3      488        5         1        1/07/2018
  4      488        1         2        7/07/2018
  5      488        1         2        7/07/2018
  6      488        1         2        7/07/2018
  7      488        1         3        16/07/2018
  8      488        1         3        16/07/2018
  9      488        1         3        16/07/2018

结果应为:7、8、9,我的实际查询正确返回了此值,但假设所有matches的值为status 5(因此所有matches都已播放),查询将返回空结果。

因此,我尝试处理这种情况以返回最后一个gameweek(如果matches的所有round都已播放),但是我得到了:

  

SQLSTATE [42000]:语法错误或访问冲突:1140在没有GROUP BY的聚合查询中,SELECT列表的表达式#1包含非聚合列'y.gameweek';这与sql_mode = only_full_group_by

不兼容

这是我的查询

SELECT m.id, m.round_id, m.datetime,
  CASE m.status
    WHEN 1 THEN 'scheduled'
    WHEN 2 THEN 'postponed'
    WHEN 3 THEN 'canceled'
    WHEN 4 THEN 'playing'
    WHEN 5 THEN 'finished'
  END AS match_status,
  m.gameweek, m.home_team_id, m.home_team_half_time_score, m.home_team_score,
  m.home_extra_time, m.home_penalties, m.away_team_id, m.away_team_half_time_score,
  m.away_team_score, m.away_extra_time, m.away_penalties, m.venue_id,
  m.venue_attendance, m.aggregate_match_id,
  t.name AS home_team_name,
  t_info.shield_link AS home_team_shield,
  t2.name AS away_team_name,
  t2_info.shield_link AS away_team_shield,
  c.name AS competition_name,
  c.id AS competition_id,
  r.name AS round_name
  FROM `match` m
  LEFT JOIN team t ON m.home_team_id = t.id
  LEFT JOIN team_info t_info ON t.id = t_info.team_id
  LEFT JOIN team t2 ON m.away_team_id = t2.id
  LEFT JOIN team_info t2_info ON t2.id = t2_info.team_id
  LEFT JOIN competition_rounds r ON m.round_id = r.id
  LEFT JOIN competition_seasons s ON r.season_id = s.id
  LEFT JOIN competition c ON c.id = s.competition_id
  WHERE 1 AND m.status IN (1, 2, 3, 4, 5) AND m.round_id IN (:round_id1) AND m.gameweek = (SELECT COALESCE(y.gameweek, MAX(x.gameweek)) gameweek
  FROM `match` x
  LEFT JOIN
  (SELECT MIN(gameweek) gameweek
     FROM `match`
    WHERE status < 5
  ) y ON y.gameweek = x.gameweek ) ORDER BY m.datetime DESC LIMIT 10 

我该如何解决?

谢谢。

其他详细信息

在查询的第一部分中,我仅选择要从联接表中返回的字段。使用存储所有匹配项的主表匹配项进行选择。我在表team和team_info上加入了join,后者获取了参加比赛的两个团队的信息。

在此之后,我加入了Competition_rounds,获取了该回合的详细信息,该回合仅仅是比赛的组织,与赛季相同,例如:

round.name = Regular Season | season.id = 5 season.name = 2017/2018 | id = 5

这个问题并不是很重要,但是我试图解释所有查询活动。

在where子句中,我获得所有具有所有可用状态作为状态的匹配项:1、2、3、4、5(您可以在查询字段选择器案例中找到状态描述)。后来我还有一个过滤器,返回这些回合中所有的比赛:10、488、392、70。

1 个答案:

答案 0 :(得分:1)

这是导致问题的查询部分:

public class Test {
    public static final Test TEST_VALUE = new Test(42);
    public static final Test OTHER_TEST_VALUE = new Test(1337);

    private int val;
    private final String oldEnumName;
    private Test(int val, String oldEnumName) {
        this.val = val;
        this.oldEnumName = oldEnumName;
    }

    public void increment() {
        val++;
    }

    public int getVal() {
        return val;
    }

    public String name() {
        return oldEnumName;
    }

   public static Test valueOf(String name)
   ...

问题是m.gameweek = (SELECT COALESCE(y.gameweek, MAX(x.gameweek)) gameweek FROM `match` x LEFT JOIN (SELECT MIN(gameweek) gameweek FROM `match` WHERE status < 5 ) y ON y.gameweek = x.gameweek ) 未聚合。您可以通过添加y.gameweek来解决此问题:

GROUP BY y.gameweek

但是,更简单的表达式是:

m.gameweek = (SELECT COALESCE(y.gameweek, MAX(x.gameweek)) gameweek
              FROM `match` x LEFT JOIN
                   (SELECT MIN(gameweek) gameweek
                    FROM `match`
                    WHERE status < 5
                   ) y
                   ON y.gameweek = x.gameweek
              GROUP BY y.gameweek
             ) 

m.gameweek = (SELECT m2.gameweek FROM `match` m2 ORDER BY (status < 5) DESC, (CASE WHEN status < 5 THEN gameweek END) ASC, gameweek DESC LIMIT 1 ) 的第一个键将带有ORDER BY的行放在第一位。第二个按status < 5的顺序升序排列。因此,结果是第一行将是gameweek,最小值为status < 5

这些都不存在,然后第三个键起作用,您将获得最大值。

另一个版本使用条件聚合:

gameweek