Sql Server复杂子查询

时间:2011-11-07 19:15:03

标签: sql sql-server sql-server-2005 subquery

考虑这两个表:

CREATE TABLE GAME_ROUNDS(
    RoundId int primary key NOT NULL,
    GameId int NOT NULL,
    RoundNumber int NOT NULL,
    Value varchar(20) ,
    Guess varchar(20) ,
    Answer varchar(20) ,
    Correct bit NOT NULL,       
    Seconds int NOT NULL,
    Milliseconds int NOT NULL)

CREATE TABLE GAMES(
    GameId int  primary key NOT NULL,
    GameTypeId int NOT NULL,
    GameDate datetime NOT NULL,     
    GameValues varchar(500) null)

以下是一些示例数据:

insert into games(gameid, gametypeid, gamedate, gamevalues) values(1, 1,'2011-11-01 08:00:16.790',NULL)
insert into games(gameid, gametypeid, gamedate, gamevalues) values(2, 1,'2011-11-02 10:48:37.257',NULL)
insert into games(gameid, gametypeid, gamedate, gamevalues) values(3, 1,'2011-11-03 15:35:52.160',NULL)
insert into games(gameid, gametypeid, gamedate, gamevalues) values(4, 1,'2011-11-03 14:35:52.160',NULL)
insert into games(gameid, gametypeid, gamedate, gamevalues) values(5, 2,'2011-10-30 21:28:27.803','00,01,02,03,04,05,06,07,08,09')
insert into games(gameid, gametypeid, gamedate, gamevalues) values(6, 2,'2011-11-02 21:28:14.770','00,01,02,03,04,05,06,07,08,09')
insert into games(gameid, gametypeid, gamedate, gamevalues) values(7, 2,'2011-11-03 21:28:14.770','00,01,02,03,04,05,06,07,08,09')
insert into games(gameid, gametypeid, gamedate, gamevalues) values(8, 2,'2011-11-04 21:32:15.470','10,11,12,13,14,15,16,17,18,19')
insert into games(gameid, gametypeid, gamedate, gamevalues) values(9, 2,'2011-11-05 22:32:15.470','10,11,12,13,14,15,16,17,18,19')
insert into games(gameid, gametypeid, gamedate, gamevalues) values(10, 2,'2011-11-06 21:32:15.470','10,11,12,13,14,15,16,17,18,19')

insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(1, 1, 1,'Feb', '4', '4', 1, 0, 500)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(2, 1, 2,'Jul', '0', '0', 1, 0, 500)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(3, 1, 3,'Mar', '4', '4', 1, 0, 531)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(4, 2, 1,'Dec', '6', '6', 1, 0, 437)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(5, 2, 2,'May', '2', '2', 1, 0, 484)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(6, 2, 3,'Sep', '6', '6', 1, 0, 500)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(7, 3, 1,'Mar', '4', '3', 0, 0, 515)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(8, 3, 2,'Apr', '0', '0', 1, 0, 484)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(9, 3, 3,'May', '2', '2', 1, 0, 500)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(10, 4, 1,'Oct', '1', '1', 1, 0, 468)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(11, 4, 2,'Jan', '1', '1', 1, 0, 500)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(12, 4, 3,'Nov', '4', '4', 1, 0, 484)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(13, 5, 1,'0', '0', '0', 1, 0, 637)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(14, 5, 2,'5', '6', '6', 1, 0, 875)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(15, 5, 3,'8', '3', '3', 1, 0, 531)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(16, 6, 1,'9', '4', '4', 1, 0, 472)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(17, 6, 2,'6', '0', '0', 1, 0, 563)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(18, 6, 3,'8', '3', '3', 1, 0, 443)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(19, 7, 1,'0', '0', '0', 1, 0, 468)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(20, 7, 2,'9', '4', '4', 1, 0, 456)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(21, 7, 3,'4', '5', '5', 1, 0, 547)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(22, 8, 1,'12', '1', '1', 1, 0, 615)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(23, 8, 2,'18', '1', '1', 1, 0, 701)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(24, 8, 3,'16', '6', '6', 1, 0, 515)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(25, 9, 1,'10', '5', '5', 1, 0, 500)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(26, 9, 2,'19', '2', '2', 1, 0, 546)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(27, 9, 3,'15', '4', '4', 1, 0, 515)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(28, 10, 1,'13', '2', '2', 1, 0, 484)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(29, 10, 2,'12', '1', '1', 1, 0, 484)
insert into game_rounds(roundid, gameid, roundnumber, value, guess, answer, correct, seconds, milliseconds) values(30, 10, 3,'11', '6', '6', 1, 0, 453)

这些表格是我正在处理的记忆游戏的一部分。细节并不重要但是当你玩游戏时你的猜测时间会有所改善。

一个例子是一个游戏,你必须在提交月份时给出月份代码。所以Oct = 1,Nov = 4,Dec = 6等。

我想写一个查询,告诉我每个gametypeid和gamevalues组合gameid,其中平均猜测达到500毫秒。

这是我到目前为止所做的:

select vt.gametypeid, vt.gamevalues, min(vt.gamedate)
from (
         select dg.gametypeid, dg.gameid, dg.gamedate, dg.gamevalues, count(gr.gameid) as numberofrounds, cast(sum(gr.seconds*1000 + gr.milliseconds) as decimal)/cast(count(gr.gameid) as decimal) as avgguessmilliseconds
         from game_rounds gr (nolock)
         inner join games dg (nolock) on dg.gameid = gr.gameid
         where gr.gameid not in(select gameid from game_rounds (nolock) where correct = 0)
         group by gr.gameid, dg.gametypeid, dg.gamevalues, dg.gamedate, dg.gameid, dg.gamedate
         having cast(sum(gr.seconds*1000 + gr.milliseconds) as decimal)/cast(count(gr.gameid) as decimal) <= 500
) vt
group by vt.gametypeid, vt.gamevalues

结果如下

gametypeid  gamevalues                                         gamedate
----------- -------------------------------------------------- -----------------------
1           NULL                                               2011-11-02 10:48:37.257
2           00,01,02,03,04,05,06,07,08,09                      2011-10-30 21:28:27.803
2           10,11,12,13,14,15,16,17,18,19                      2011-11-04 21:32:15.470

问题是我没有GameId引用回来。我不想在我的结果集中重新获得gameid。

有没有办法使用纯SQL(没有游标或表变量)?

2 个答案:

答案 0 :(得分:1)

我犹豫不决的回答是“是”。我认为APPLY运算符适合您,因为您需要每行结果而不使用游标或表变量。请查看此Link

答案 1 :(得分:1)

我想这会帮到你。我假设你想要的是符合指定标准的第一款游戏(因为你在你的例子中使用了游戏命令的最小值)。显然,每个gametypeid / values组合可能有多个游戏适合该账单。

SELECT GameId, 
       GameTypeId, 
       GameValues, 
       GameDate 
FROM
(
   SELECT   G.GameId,
        G.GameTypeId,
        G.GameValues,
        G.GameDate,
        RANK() OVER(Partition By G.GameTypeId, G.GameValues Order By
               G.GameDate DESC) As Ranking 
    FROM    GAMES G
    JOIN    GAME_ROUNDS GR
        ON  G.GameId = GR.GameId
    GROUP
    BY      G.GameId,
        G.GameTypeId,
        G.GameValues,
        G.GameDate
    HAVING  SUM(CASE GR.Correct WHEN 0 THEN 1 ELSE 0 END) = 0
    AND     AVG(CAST(GR.Seconds * 1000 + GR.Milliseconds as DECIMAL)) <= 500
) CandidateResults
WHERE   Ranking = 1