如何让sql查询只返回1行?或者如何将2个结果合并或组合成1

时间:2014-11-22 03:22:34

标签: mysql sql database performance laravel-4

问题:

  • 如何合并或将2队结果合并为1?或
  • 如何让它只返回1行?

表名: series_type

id| type| description 
1 |    0| No series (Any team win 1 will be the winner)
2 |    1| Best of 3 (Any team wins 2 will be the winner else draw)
3 |    2| Best of 5 (Any team wins 3 will be the winner else draw)

表名: 团队

       ID| name 
  1848158| LV
       15| LGD

表名: 匹配

ID| series_id | series_type | league_id | start_time |radiant_name | dire_name | radiant_win
1 |      8313 |           2 |      2096 |   xxxxxxx1 |          LV |       LGD | true 
2 |      8313 |           2 |      2096 |   xxxxxxx2 |         LGD |        LV | false
3 |      8313 |           2 |      2096 |   xxxxxxx3 |          LV |       LGD | false
4 |      8313 |           2 |      2096 |   xxxxxxx4 |          LV |       LGD | false
5 |      8313 |           2 |      2096 |   xxxxxxx5 |         LGD |        LV | false

查询:

SELECT series_id, team, SUM(Win) As Won, SUM(Loss) as Lost
FROM
( SELECT *,radiant_name as team, 
     CASE WHEN radiant_win = 1 THEN 1 ELSE 0 END as Win, 
     CASE WHEN radiant_win = 1 THEN 0 ELSE 1 END as Loss
  FROM matches
  UNION ALL
  SELECT *,dire_name as team, 
     CASE WHEN radiant_win = 0 THEN 1 ELSE 0 END as Win, 
     CASE WHEN radiant_win = 0 THEN 0 ELSE 1 END as Loss
  FROM matches
) as temp
WHERE series_id = 8313
GROUP By team
ORDER By Won, Lost DESC

结果 group by series_id

series_id| team| Won| Lost|
     8313|   LV|   5|    5|

结果 按团队分组

series_id| team| Won| Lost|
     8313|  LGD|   2|    3|
     8313|   LV|   3|    2|

预期结果: 我需要按series_id分组

series_id| teamA| teamB| teamAWon| teamBWon| teamALost| teamBLost|
     8313|    LV|   LGD|        3|        2|         2|         3|

2 个答案:

答案 0 :(得分:1)

主要的复杂因素是每个团队名称可以在radiant_name或dire_name中出现0次或更多次。因此,根据团队名称将团队分成一列,这有点复杂。如果匹配具有常量teamA和teamB列,然后是一列用于指示哪个团队是辐射的,另一列用于指示哪个团队获胜,那将更容易。

这几乎肯定不是最佳的,但似乎有效:

-- create a two-column temp table with series ID and team name, insert rows from matches
-- we'll wind up with one row per distinct radiant_name and distinct dire_name,
-- so up to 4 rows for a series
CREATE TEMPORARY TABLE IF NOT EXISTS tempteama AS
select distinct series_id, radiant_name AS team
from matches
union
select distinct series_id, dire_name AS team
from matches;

-- do this again in a second temp table, so we can join the two later
-- (MySQL doesn't like to join temp tables against themselves)
CREATE TEMPORARY TABLE IF NOT EXISTS tempteamb AS
select distinct series_id, radiant_name AS team
from matches
union
select distinct series_id, dire_name AS team
from matches;

-- join matches against the temp table to get final results
select matches.series_id, 
teamA, 
teamB, 
sum(case when (radiant_name = teamA AND radiant_win=1) OR (dire_name=teamA AND radiant_win=0) then 1 else 0 end) AS teamA_win,
sum(case when (radiant_name = teamB AND radiant_win=1) OR (dire_name=teamB AND radiant_win=0) then 1 else 0 end) AS teamB_win
from matches
join (
-- select just one row from the temp table. That gives us the combination of teams for the series.
select tempteama.series_id, tempteama.team AS teamA, tempteamb.team AS teamB
from tempteama
join tempteamb on tempteama.series_id = tempteamb.series_id and tempteama.team != tempteamb.team
limit 1
) AS teamnames on teamnames.series_id = matches.series_id
group by matches.series_id, teamA, teamB;

您可能会将临时表查询作为子查询进行,但会牺牲一些可读性。

答案 1 :(得分:0)

对于这个问题,我有两个结果,一个用于oracle sql的任何sql和其他(因为我在其中使用了oracle函数)

可以在任何sql上运行此解决方案: -

SELECT AB.SERIES_ID,TEAMA,TEAMB ,TEAMAWON,COUNT(STC.SERIES_ID)-TEAMAWON TEAMBWON,
COUNT(STC.SERIES_ID)-TEAMAWON TEAMALOST,
COUNT(STC.SERIES_ID)-(COUNT(STC.SERIES_ID)-TEAMAWON) TEAMBLOST FROM  
(
  SELECT MA.SERIES_ID,MA.RADIANT_NAME TEAMA,MA.DIRE_NAME TEAMB ,
  COUNT(RADIANT_WIN) TEAMAWON FROM MATCHES MA,SERIES_TYPE ST
  WHERE  MA.SERIES_TYPE=ST.TYPE   
  GROUP BY MA.SERIES_ID,MA.RADIANT_NAME,DIRE_NAME
) AB, MATCHES STC 
WHERE (AB.SERIES_ID,AB.TEAMAWON) IN
  (
    SELECT SERIES_ID,MAX(RADIANT_WIN) RAD
    FROM
    (
        SELECT MA.SERIES_ID,MA.RADIANT_NAME ,COUNT(RADIANT_WIN) RADIANT_WIN 
        FROM  MATCHES MA,SERIES_TYPE ST
        WHERE  MA.SERIES_TYPE=ST.TYPE   
        GROUP BY MA.SERIES_ID,MA.RADIANT_NAME,DIRE_NAME
    )
     GROUP BY SERIES_ID
 ) AND STC.SERIES_ID=AB.SERIES_ID AND  TEAMA IN (RADIANT_NAME,DIRE_NAME)
 GROUP BY AB.SERIES_ID,TEAMA,TEAMB ,TEAMAWON;

现在我正在为使用oracle寻求相同结果的oracle人员编写解决方案: -

SELECT SERIES_ID,GREATEST(RADIANT_NAME,DIRE_NAME) TEAMA,
LEAST(RADIANT_NAME,DIRE_NAME) TEAMB ,max(RADIANT_WIN) TEAMAWON,
SUM(RADIANT_WIN)-max(RADIANT_WIN) TEAMBWON,
SUM(RADIANT_WIN)-max(RADIANT_WIN) TEAMALOST,
SUM(RADIANT_WIN)-(SUM(RADIANT_WIN)-Max(RADIANT_WIN)) TEAMBLOST
FROM
(
   SELECT MA.SERIES_ID,MA.RADIANT_NAME,DIRE_NAME ,
   COUNT(RADIANT_WIN) RADIANT_WIN FROM MATCHES MA,SERIES_TYPE ST
   WHERE  MA.SERIES_TYPE=ST.TYPE 
   GROUP BY MA.SERIES_ID,MA.RADIANT_NAME,DIRE_NAME
) GROUP BY SERIES_ID,
  greatest(RADIANT_NAME,DIRE_NAME) ,least(RADIANT_NAME,DIRE_NAME);