Sql 避免在“WITH”不可用时重复子查询

Sql 避免在“WITH”不可用时重复子查询,sql,mysql,subquery,Sql,Mysql,Subquery,MySQL v5.0.58 为简洁起见,省略了带有外键约束等的表和其他不相关的详细信息: CREATE TABLE `fixture` ( `id` int(11) NOT NULL auto_increment, `competition_id` int(11) NOT NULL, `name` varchar(50) NOT NULL, `scheduled` datetime default NULL, `played` datetime default NULL,

MySQL v5.0.58

为简洁起见,省略了带有外键约束等的表和其他不相关的详细信息:

CREATE TABLE `fixture` (
  `id` int(11) NOT NULL auto_increment,
  `competition_id` int(11) NOT NULL,
  `name` varchar(50) NOT NULL,
  `scheduled` datetime default NULL,
  `played` datetime default NULL,
  PRIMARY KEY  (`id`)
);

CREATE TABLE `result` (
  `id` int(11) NOT NULL auto_increment,
  `fixture_id` int(11) NOT NULL,
  `team_id` int(11) NOT NULL,
  `score` int(11) NOT NULL,
  `place` int(11) NOT NULL,
  PRIMARY KEY  (`id`)
);

CREATE TABLE `team` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
);
其中: 绘图将把result.place设置为0 否则,result.place将包含一个表示第一位、第二位等的整数

任务是返回一个字符串,描述给定团队在给定比赛中最近的比赛结果。格式应为def X队,如果给定的队获胜,则为Y队;如果给定的队输了,则为输给X队;如果有平局,则为与X队平局。是的,从理论上讲,每场比赛可能会有两支以上的球队,尽管1对1是最常见的情况

这是可行的,但感觉非常低效:

SELECT CONCAT(
    (SELECT CASE `result`.`place` 
        WHEN 0 THEN "drew with"
        WHEN 1 THEN "def"
        ELSE "lost to"
        END
    FROM `result`
    WHERE `result`.`fixture_id` = 
        (SELECT `fixture`.`id` FROM `fixture`
        LEFT JOIN `result` ON `result`.`fixture_id` = `fixture`.`id`
        WHERE `fixture`.`competition_id` = 2
        AND `result`.`team_id` = 1
        ORDER BY `fixture`.`played` DESC
        LIMIT 1)
    AND `result`.`team_id` = 1),
    ' ',
    (SELECT GROUP_CONCAT(`team`.`name`)
    FROM `fixture`
    LEFT JOIN `result` ON `result`.`fixture_id` = `fixture`.`id`
    LEFT JOIN `team` ON `result`.`team_id` = `team`.`id`
    WHERE `fixture`.`id` = 
        (SELECT `fixture`.`id` FROM `fixture`
        LEFT JOIN `result` ON `result`.`fixture_id` = `fixture`.`id`
        WHERE `fixture`.`competition_id` = 2
        AND `result`.`team_id` = 1
        ORDER BY `fixture`.`played` DESC
        LIMIT 1)
    AND `team`.`id` != 1)
)

我是否错过了一些非常明显的东西,或者我不应该在一个查询中尝试这样做?或者,当前的困难是否反映了糟糕的表设计?

尝试选择需要的数据—目标团队的团队名称和位置,然后将其组合起来。对于每个赛程的两支球队:

SELECT CASE `recent`.`place` 
        WHEN 0 THEN CONCAT("drew with ", other_name)
        WHEN 1 THEN CONCAT("def ", other_name, ", ", targ_name)
        ELSE CONCAT("lost to ", other_name)
    END
FROM (SELECT rtarg.place, targ.name AS targ_name, other.name AS other_name
        FROM `fixture`
        JOIN `result` AS rtarg ON `rtarg`.`fixture_id` = `fixture`.`id`
        JOIN `team` AS targ ON `rtarg`.`team_id` = `targ`.`id`
        JOIN `result` AS rother ON `rother`.`fixture_id` = `fixture`.`id`
        JOIN `team` AS other ON `rother`.`team_id` = `other`.`id`
        WHERE `fixture`.`competition_id` = 2
          AND `rtarg`.`team_id` = @targ
          AND `rother`.`team_id` != @targ
        ORDER BY `fixture`.`played` DESC
        LIMIT 1) AS `recent`;
每个fixture可以处理两个以上的团队,只需很少的修改,尽管其他子查询也可以

SELECT CASE `recent`.`place` 
        WHEN 0 THEN CONCAT("drew with ", other_names)
        WHEN 1 THEN CONCAT("def ", other_names, "; ", targ_name)
        ELSE CONCAT("lost to ", other_names)
    END
FROM (SELECT rtarg.place, targ.name AS targ_name, GROUP_CONCAT(other.name SEPARATOR ', ') AS other_names
        FROM `fixture`
        JOIN `result` AS rtarg ON `rtarg`.`fixture_id` = `fixture`.`id`
        JOIN `team` AS targ ON `rtarg`.`team_id` = `targ`.`id`
        JOIN `result` AS rother ON `rother`.`fixture_id` = `fixture`.`id`
        JOIN `team` AS other ON `rother`.`team_id` = `other`.`id`
        WHERE `fixture`.`competition_id` = 2
          AND `targ`.`id` = @targ
          AND `rother`.`team_id` != @targ
          AND ((rtarg.place<=1 AND rother.place >= rtarg.place)
            OR (rtarg.place>1 AND rother.place < rtarg.place))
        GROUP BY fixture.id
        ORDER BY `fixture`.`played` DESC
        LIMIT 1
) AS recent;

没有指定每场比赛两支以上球队的结果格式,因此可能需要进一步调整。

我刚刚意识到“输给”的情况需要更仔细的处理,因为它实际上应该只列出获胜球队。一场比赛可能有多少支球队参加?我没有一个固定的界限,因此,我目前的表格设计中,夹具与结果是分开的。有些游戏我们这里说的电脑游戏每场比赛有三方或更多方,例如RTS,如《战争的黎明》。当每场比赛有两支以上的球队时,输出格式应该是什么?特别是,是否应列出击败败队的每支球队,例如目标是Z队:输给X队、Y队?是否应将每个失败的团队列为获胜团队,例如,目标是X团队:def Y团队、Z团队;X队?如果是这样的话,获胜的队伍应该是最后一个列出的队伍,还是应该用一个不同的分隔符(例如“;”)将其与其他队伍分开而不是“,”?是的,我认为如果球队输了,只有赢家的位置=1应该列为输给X队。如果球队赢了,所有输的球队都应该列出来。我喜欢这种方法,但不幸的是,它不允许每场比赛有两支以上的球队。除非我误解了,你明白了。我将很快更新我的答案,为每个赛程提供两个以上团队的另一个查询。非常感谢您的帮助!