| View previous topic :: View next topic |
| Author |
Message |
FlipFlop
Joined: 06 Aug 2007 Posts: 7
|
Posted: Mon Aug 06, 2007 1:08 am Post subject: n:m query problem |
|
|
Hello guys!
I have a "maybe" simple problem which caused me to stay awake for some nights... Here is the problem:
I have 3 tables:
MEMBERS (contains many members who can do more than one sport)
SPORTS (contains many sports e.g. BMX, Skateboard,...)
MEM2SPORTS (contains the linking between member_id and sports_id)
The result of this tables should be rendered by DataGrid to a table that should look like:
| Code: | [Forename] - [Surname] - [...] - [BMX] - [Skateboard] - [...]
testname - testname - ... - Yes - No - ...
...and so on...
|
As you can see the data sources are not practicable for a single query but as far as I know bind() does only accept a single query, a db ressource or an array. So the first two can't be used and I tried it with an array which I prepared for my needs.
To get an idea of the array:
| Code: | [MemID][Forename] testname
[Surname] testname
[...] ...
[BMX] Yes
[Skateboard] No
[...] ... |
Now the next problem came up:
By using an array I loose the feature of limiting the query in case of paging, because at the preparing time of the array I don't know what records to show (normally this will be done automatically by DataGrid) and if there are many members I can't do a select without limiting it.
I think this can be solved by asking getCurrentPage(), but is this really a good way? Seems to become complicated, or?
Anyway, I got it working with the array but up to now the array holds all records of members! And it's getting worse by looking at the array which holds all relations between members and sports -> this array can become very very huge.
Does anyone know how I can put my 3 tables together to provide DataGrid a useable datasource? Is an array the only solution?
Many thanks for any hints and tipps on this issue!!
(I hope my description is not too abstruse...)
Bye
Mike |
|
| Back to top |
|
 |
mark

Joined: 07 Jan 2007 Posts: 1053
|
Posted: Mon Aug 06, 2007 12:04 pm Post subject: |
|
|
I might overlook something, but can't you use joins in a single query to fetch the data from your three tables?
The limiting feature would then still be used, and even counting should work as expected as long as you don't need to group records (if you need to, you can use the 'count_query' option).
I can provide another idea if joins don't solve your problem, but that idea would require more work for you. |
|
| Back to top |
|
 |
alex
Joined: 13 Sep 2006 Posts: 72
|
Posted: Mon Aug 06, 2007 3:35 pm Post subject: |
|
|
| Quote: | | I might overlook something, but can't you use joins in a single query to fetch the data from your three tables? |
Mark : it seems he needs a "special" appareance for the html table. Joining would only works using "GROUP BY" I think but he only will get a column "sports" with all sport of users listed and not a column for each sport. |
|
| Back to top |
|
 |
mark

Joined: 07 Jan 2007 Posts: 1053
|
Posted: Mon Aug 06, 2007 3:42 pm Post subject: |
|
|
| alex wrote: | | Mark : it seems he needs a "special" appareance for the html table. Joining would only works using "GROUP BY" I think but he only will get a column "sports" with all sport of users listed and not a column for each sport. |
Hmm, we're planning some linking feature between datagrids. Olivier has an example available on his homepage.
But let's see what he really wants to have. |
|
| Back to top |
|
 |
FlipFlop
Joined: 06 Aug 2007 Posts: 7
|
Posted: Mon Aug 06, 2007 5:05 pm Post subject: |
|
|
Hi there,
Alex got me right. With an INNER JOIJN query I get as result for each sport per member a seperate record. So if a member was added to 2 sports mysql resturns 2 records for this member. For example such a result looks like:
| Code: | [ID] [forname] [...] [Sport] [...]
1 testname1 ... BMX ...
1 testname1 ... Skateboard ... |
And that's neither a good idea for displaying nor for dealing with data because of many redundants in the results.
A perfect result would be
| Code: |
[ID] [forname] [...] [BMX] [Skateboard] [...]
1 testname1 ... Yes Yes ...
2 testname2 ... Yes No ...
|
...but seems to become pretty difficult.
@mark: what else ideas do you have?
Mike |
|
| Back to top |
|
 |
alex
Joined: 13 Sep 2006 Posts: 72
|
Posted: Mon Aug 06, 2007 6:01 pm Post subject: |
|
|
| Quote: | | Alex got me right. With an INNER JOIJN query I get as result for each sport per member a seperate record. So if a member was added to 2 sports mysql resturns 2 records for this member |
As I said you could use "GROUP BY" clause and "GROUP_CONCAT" (then implode()) to get one line per member like this :
| Code: |
[ID] [forname] [...] [Sports] [...]
1 testname1 ... BMX ...
Skateboard
2 testname2 ... Skateboard ...
|
or you could use a 2nd query in a formatter function ...
Maybe it is possible to get what you want (waiting for Mark's answer) but when I have such a case I use what I said above ... |
|
| Back to top |
|
 |
FlipFlop
Joined: 06 Aug 2007 Posts: 7
|
Posted: Mon Aug 06, 2007 7:03 pm Post subject: |
|
|
Will wait for mark too, but maybe you have also a good way to what I have some questions:
How does DataGrid know that member 1 has more than one sport and further more put an additional column to the table?
And how can I use implode() in your sense? Once the query is passed to bind() I can't make anything with it except looking at my poor table
ps: If necessary I can post the whole sql dump of my tables so you can define your idea of a query better (I own up to be not a sql guru)
Will have a look at the formatter function in the meantime. |
|
| Back to top |
|
 |
mark

Joined: 07 Jan 2007 Posts: 1053
|
Posted: Mon Aug 06, 2007 9:12 pm Post subject: |
|
|
Okay, I now got the idea (an example is always good, BTW). Grouping would be an option, like Alex suggested. But that would generate multiple rows for the different sports -- possible, but maybe not the wanted way. (Doing some magic with formatter functions might help here.)
Another possiblity would be to write your own DataSource driver. This gives you the full flexibility over the data and the columns. Whenever a new sport occurs while fetching the data, a new column could be added. I'd suggest, though, that you get a list of all sports at first, to make a concise number of columns through all pages, and not three on page 1, seven on page 2, four on page 3 etc.
This might sound complex. It's not as easy as simply binding a SQL query, but it is possible. A good start might be two start the work from the MDB2 driver (from CVS because we heavily refactored the handling of SQL queries since the last releases).
If needed, I can provide more help / details here. |
|
| Back to top |
|
 |
FlipFlop
Joined: 06 Aug 2007 Posts: 7
|
Posted: Tue Aug 07, 2007 8:41 am Post subject: |
|
|
Hi mark!
Sounds great and smells of a lot of work
I think the solution with the data source driver would be the best way, as you wrote it gives more flexibility. And regarding the sport columns: Yes the will and must have a concise number of columns through all pages. If e.g. 5 sports exists and a member was only added to one sport the rest 4 columns are displayed as well with value "No".
Since analyzing either foreign or old self-code is time-consuming it would be very appreciated if you can provide more details of how to rewrite the MDB2 driver for my special needs.
Many thanks in advance!
Mike |
|
| Back to top |
|
 |
mark

Joined: 07 Jan 2007 Posts: 1053
|
Posted: Tue Aug 07, 2007 7:17 pm Post subject: |
|
|
| FlipFlop wrote: | | Since analyzing either foreign or old self-code is time-consuming it would be very appreciated if you can provide more details of how to rewrite the MDB2 driver for my special needs. |
Sorry, but explaining every bit is also time-consuming. I've already provided many hints in my last answer. This should give you the ability to look into the right places of the code (remember: the CVS version is the best place).
The starting point, however, would be to get the different sports with a SQL query and to create the columns. The main SQL query could be put into your driver, which would make the bind() call rather short:
$datagrid->bind(null, null, 'NameOfYourDriver');
The problem of setting the "Yes"/"No" values for each record and each sport column could be solved maybe by some magic in your driver: You know the number of sports, and you know which values you expect. I haven't thought about this more deeply, but it should be solvable.
If you have more questions (especially on details and SDG's internal structures), don't hesitate to ask. |
|
| Back to top |
|
 |
|