tadhg.com
tadhg.com
 

sfmagic.org Rewrite: Head-to-Head Some Working SQLAlchemy

23:56 Sun 13 Jan 2008. Updated: 01:52 14 Jan 2008
[, , , ]

I haven’t had much time to work on the project over the weekend, but I have made some progress in getting the queries into SQLAlchemy form.

Having found no further documentation on IF statements, I decided that I should probably rewrite the SQL itself using another approach, so I tried subqueries:

select
    sum(a.wins + b.wins), sum(a.losses + b.losses), sum(a.draws + b.draws)
    from
        (select
            sum(wins) as wins, sum(losses) as losses, sum(draws) as draws
            from h2hresults
                where
                    player1=99 and player2=4
        ) as a,
        (select
            sum(losses) as wins, sum(wins) as losses, sum(draws) as draws
            from h2hresults
                where
                    player1=4 and player2=99
        ) as b;

That returns the game record between players 4 and 99. It took me quite a while to get to the SQLAlchemy for for that, partly because of the use of label() or as_scalar(). I’m still fairly sure that this version isn’t quite right:

select([
    func.sum(
        select([
            func.sum(h2hresults_table.c.wins)], h2hresults_table.c.player1==player1id)
        .where(h2hresults_table.c.player2==player2id).as_scalar()
        + 
        select([
            func.sum(h2hresults_table.c.losses)], h2hresults_table.c.player1==player2id)
        .where(h2hresults_table.c.player2==player1id).as_scalar()
    ).label('wins'),
    func.sum(
        select([
            func.sum(h2hresults_table.c.losses)], h2hresults_table.c.player1==player1id)
        .where(h2hresults_table.c.player2==player2id).as_scalar()
        + 
        select([
            func.sum(h2hresults_table.c.wins)], h2hresults_table.c.player1==player2id)
        .where(h2hresults_table.c.player2==player1id).as_scalar()
    ).label('losses'),
    func.sum(
        select([
            func.sum(h2hresults_table.c.draws)], h2hresults_table.c.player1==player1id)
        .where(h2hresults_table.c.player2==player2id).as_scalar()
        + 
        select([
            func.sum(h2hresults_table.c.draws)], h2hresults_table.c.player1==player2id)
        .where(h2hresults_table.c.player2==player1id).as_scalar()
    ).label('draws'),
])

It works, but the SQL it actually sends to the server looks something like this:

SELECT sum(
        (SELECT sum(h2hresults.wins) 
        FROM h2hresults 
        WHERE h2hresults.player1 = :h2hresults_player1_1 AND h2hresults.player2 = :h2hresults_player2_1)
        +
        (SELECT sum(h2hresults.losses) 
        FROM h2hresults 
        WHERE h2hresults.player1 = :h2hresults_player1_2 AND h2hresults.player2 = :h2hresults_player2_2)
    ) AS wins,
    sum(
        (SELECT sum(h2hresults.losses) 
        FROM h2hresults 
        WHERE h2hresults.player1 = :h2hresults_player1_3 AND h2hresults.player2 = :h2hresults_player2_3)
        +
        (SELECT sum(h2hresults.wins) 
        FROM h2hresults 
        WHERE h2hresults.player1 = :h2hresults_player1_4 AND h2hresults.player2 = :h2hresults_player2_4)
    ) AS losses,
    sum(
        (SELECT sum(h2hresults.draws) 
        FROM h2hresults 
        WHERE h2hresults.player1 = :h2hresults_player1_5 AND h2hresults.player2 = :h2hresults_player2_5)
        +
        (SELECT sum(h2hresults.draws) 
        FROM h2hresults 
        WHERE h2hresults.player1 = :h2hresults_player1_6 AND h2hresults.player2 = :h2hresults_player2_6)
    ) AS draws

That, clearly, is not the same as the SQL I started out with, although perhaps it’s more logical and straightforward as an approach. Hopefully the other queries (match record between two players, and who player X has the most match wins against) won’t be too tough, and I’ll be done with head-to-head shortly.

Leave a Reply