tags:

views:

54

answers:

2

I have been asked to post a new question about how to correctly sort my data. Here is what I am trying to do. I want to make a single trip to my database for all of the data that I will need for this page. Once I have the data returned from the database, I need to sort it out and use it.

For brevity, I am only posting a single row of data. There are, in actuality, 8 rows being returned. Here is the structure of the data that is being returned:

col1    col2    col3    col4    col5    col6    col7    col8    col9

Now, here is the problem I am having. Columns 1 through 7 hold a 1:1 dataset. Columns 8 and 9 however, hold numerous rows, hence the 8 total rows. Because I have columns 1 through 7 mixed in with the 1:M rows, I am echoing rows 1-7 7 times more than I need to.

How can I resolve this?


Let me just add that there are 4 inner joins being used in this query. One of the tables, holds page specific data that I only need to access once. The other joins are what are creating the other rows. Let me just say tat the output of this resultset is absolutely correct. I just need to figure out how to sort it.


OK, this should make sense....

dealerId  empId  lotId  rackId  porterId  vehicle  vin
1         1      1      1       1         Geo      12JI997676JH
1         1      1      1       1         Ford     87HJ879854HS
1         1      1      1       1         BMW      567876HCS456
1         1      1      1       1         Mercedez 1JI8787GS687

In this set, notice that I have 4 rows of repeating data. What I need is this:

dealerId  empId  lotId  rackId  porterId
1         1      1      1       1

AND then for the multiple rows, I need this:

vehicle  vin
Geo      12JI997676JH
Ford     87HJ879854HS
BMW      567876HCS456
Mercedez 1JI8787GS687

So, this setup now gives me the single row of my dealer data and I now have a new array with the vehicle data. :)

+1  A: 

Two options that I know of (and use, depending on how large I expect the datasets to be).

Either:
Get all rows, like you do now, and sort it out with php, with something like:

$result = array();
foreach( $rowset as $row )
{
    // if the parent row is not present in the result array (assuming col1 is PK)
    if( !isset( $result[ $row[ 'col1' ] ) )
    {
        // create it, and make arrays of col8 and col9
        $result[ $row[ 'col1' ] ] = array(
            'col1' => $row[ 'col1' ],
            'col2' => $row[ 'col2' ],
            'col3' => $row[ 'col3' ],
            'col4' => $row[ 'col4' ],
            'col5' => $row[ 'col5' ],
            'col6' => $row[ 'col6' ],
            'col7' => $row[ 'col7' ],
            'col8' => array( $row[ 'col8' ] ),
            'col9' => array( $row[ 'col9' ] )
        )
    }
    else
    {
        // the parent row is present, so push values in col8 and col9 arrays
        $result[ $row[ 'col1' ] ][ 'col8' ][] = $row[ 'col8' ];
        $result[ $row[ 'col1' ] ][ 'col9' ][] = $row[ 'col9' ];
    }
}

Or:
Make more trips to the database, by first selecting the unjoined rows, and loop trough these rows and select the child rows for them.

So, concluding: if you really only want one trip to the DB, the first option is the only available option (as far as I know).

PS:
Other options would probably be Stored Procedures or Views, but I don't have enough experience with them to give you good examples of them, especially Views (not even sure Views can be used for these purposes).

But the benefit of a Stored Procedure would be a single trip to the DB I guess.

fireeyedboy
fireeyedboy, thanks. This is exactly what I was thinking about doing but was unsure if it was correct or even the best way of handling it.
jim
@jim: I recently started relying more on multiple queries. I used to think one trip to the DB was the better thing to do, but when result sets get large, I'm not sure this is very efficient anymore, because I need PHP to parse it. I now consider this premature optimalisation anyway, and thus simply make more trips to the DB until it really starts to affect execution time. More trips are usually better readable, than the messy (IMO) PHP example I gave you. So I'ld like to suggest you think about how important it is to you, to do it all in one go, and whether it actually is beneficial.
fireeyedboy
Well, I am actually with you on this because you are right, the example is messy but it's exactly how I was doing it as well. I'm always trying to shave some time off of the load times where possible. I'm actually glad that there is another guy out there that thinks that maybe making several trips to the database isn't such a bad thing after all. I mean, looking at your example, I basically have the same thing and I have over 100 lines trying to bring everything back into something that I can actually use. It truly sucks and was what was making me search for a better way or a best practice.
jim
I just read your edit, fireeyedboy and I am currently using a stored procedure. Can you give me the logic that you were thinking about for the stored procedure? I'm not an expert at them but I can hold my own. The issue with a stored procedure is that you cannot return more than a single row at a time.
jim
@jim: I think you should just do a little benchmark with this cluttered example, and multiple trips to the DB, if you are worried about performance. I think you might be surprised how little difference it will make. Heck, I wouldn't even be surprised if the latter is faster. ;-)
fireeyedboy
Ok, I can do that. I've already got a microtime timer on the page so it wouldn't be much to test. Just have to modify my class a little. Thanks a bunch fireeyedboy. I was waiting to see what Deceze said before I gave credit to anyone. If he doesn't respond, you'll get the credit for this.
jim
@jim: well, that just goes to show how inexperienced I am with SP's. I didn't even now you couldn't return a resultset. So I'm sorry Jim, I can't help you anymore on that one.
fireeyedboy
That's OK fireeyedboy, I really appreciate your help. You actually helped me the other day out of a fine mess. :)
jim
@jim: furthermore, even if you could return a resultset, you would still be back at square one... silly me... what was I thinking. ;-)
fireeyedboy
@fireeyedboy: Yes, that's true come to think of it. :) Sometimes I'm like a dog chasing his tail thinking that there MUST be a better way of doing something that I completely lose focus of what I'm doing, such as in this case.
jim
@jim: sounds but all too familiar. ;-) Not sure I recall helping you out the other day BTW. And can't see anything in your history either. Do you have a new account by any chance? Anyway, not important. But glad I could be of help.
fireeyedboy
@fireeyedboy: Actually, I requested help with this exact same problem with rearranging an array with my database values. Who could forget a name like "Fireeyedboy"? :) Anyway, I don't have a permanent account but I always sign is as Jim. Next time you stumble across one of my posts, I'll be sure to mention it. Also, you might be interested to know that I did a test with two queries and it is actually faster. Not much, but still, it's faster! I can't believe it.
jim
@jim: Thanks for reporting back. I must admit I was bit too lazy to test it myself, but this is reassuring to hear. Until next time perhaps.
fireeyedboy
+1  A: 

OK, so the question is, how do you want to use this data? If you want to display it in this fashion, one row per vehicle, it makes sense to fetch the data JOINed and just go through it:

foreach ($row as $vehicle) {
    echo "$vehicle[vehicle] … $vehicle[dealerId]\n";
}

Each retrieved row would represent one set of related data.

If, OTOH, the JOINed vehicle data doesn't actually have to do much with the dealerIds etc, it makes a lot more sense to retrieve these two things in separate queries. It's probably faster too.

Retrieve (and store, to begin with) data in the simplest way that makes sense so you have to do as little post-massaging in your PHP code as possible. Don't set the goal to be "retrieve everything in a single query" just because. If you fear several trips to the database are too expensive, they're probably not. Your time is much more valuable than the split second it takes to make a second request.

deceze
Yes. I have to totally agree with you again because I have been banging my head against the wall trying to figure out what the fastest way to do this is. Fireeyedboy also suggested several trips to the database as well. I think this is going to be my best route. To answer your question, there is no reason why I wouldn't be able to get this data is two trips. Thanks so much for your help Deceze.
jim
@jim http://www.codinghorror.com/blog/2005/01/micro-optimization-and-meatballs.html :)
deceze
Thanks! I'm going there now. :)
jim