1

I have two tables holding game data for two different games. For the sake of simplicity, let's say they only share a column called Timestamp (in particular they have a different number of columns). I want to render a list holding information from both tables, simultaneously ordered by Timestamp.

What I'm currently doing works, but I'd take almost any bet that there is a much better way to do this. I'm mostly concerned about performance at some point (mobile app). This is a stub representing the structure – believe me, I know how horrible this looks right now. I just wanted to make it work first, now I'm looking for improvements. ;)

var readyA,
    readyB = false;

var dataA, 
    dataB;

function doLoop () {
    setTimeout(renderData, 100);
}

function renderData () {
    if (!readyA || !readyB) {
        doLoop();
        return;
    }

    var dataAll = dataA.concat(dataB);
    dataAll.sort(function (a,b) {
        return a['Timestamp'] <= b['Timestamp'];
    });

    // pass data into a template depending on from which game it is and render it
    // ...
}

// wait for both queries to finish
doLoop();

// select data from game A
myDatabaseClass.query('SELECT ... FROM GameA', function (results) {
    dataA = new Array(results.rows.length);
    for (var i=0; i<results.rows.length; i++) { 
        dataA[i] = results.rows.item(i); 
    }

    readyA = true;
});

// select data from game B
myDatabaseClass.query('SELECT ... FROM GameB', function (results) {
    dataB = new Array(results.rows.length);
    for (var i=0; i<results.rows.length; i++) { 
        dataB[i] = results.rows.item(i); 
    }

    readyB = true;
});

The question would now be if I can somehow simplify this by some kind of UNION or JOIN in the query. Obviously, the Timeout construction is horrible, but that will automatically collapse to a simple callback function if the querying can be done in one query (or at least one transaction – the database class can handle that).

Edit: I did found this ( Pull from two different tables and order ) but this whole NULL AS some_column feels dirty. Is there really no better alternative?

4

2 に答える 2

2

The result of a query always is a single table with a fixed number of columns, so all the SELECTs must have the same number of columns:

SELECT a1, a2, a3,   Timestamp FROM GameA
UNION ALL
SELECT b1, b2, NULL, Timestamp FROM GameB
ORDER BY Timestamp

(UNION ALL is faster than UNION because it doesn't try to remove duplicates.)

于 2012-11-30T14:28:52.760 に答える
1

Your code is pretty good. From the point of view of a SQL hacker like me you're doing the UNION and the ORDER BY on the client side. There's nothing wrong with that. You seem to be doing it almost right. Your "concat" is the client-side equivalent of UNION, and your "sort' is the equivalent of ORDER BY.

You say that the NULL as missing-column construction feels somehow dirty if you use server-side UNION operations. But, obviously to treat two different result sets as the same so you can sort them in order you have to make them conform to each other somehow. Your a['Timestamp'] <= b['Timestamp'] sort-ordering criterion in your sort function is also a scheme for conforming two result sets to each other. It may be lower-performance than using a UNION.

Don't be afraid of using NULL as missing-column to make two result sets in a UNION conform to each other. It's not dirty, and it's not expensive.

Do consider limiting your SELECT operation somehow, perhaps by a range of timestamps. That will allow your system to scale up, especially if you put an index on the column you use to limit the SELECT.

(By the way, your sort function has a mistake in it. sort functions need to return -1, 0, or +1 depending on whether the first item is less than, equal to, or greater than the second one. You're returning a true/false value. That doesn't work properly.)

(You're parallelizing the two queries to the same MySQL instance. That's clever, but probably in truth is a formula for overloading MySQL as your game scales up. Keep in mind that each user of your game has her own machine running Javascript but they all share your MySQL.)

于 2012-11-30T14:33:06.643 に答える