Counting records from another table

Counting records from another table

arie0512arie0512 Posts: 7Questions: 2Answers: 0
edited September 9 in Free community support

Hi there,

I am trying to count the number of residents which lives on an address.

I have 2 tables:

Address

addressnumber | Street | Zipcode | City
1 | Street 1 | 1111AA | New York
2 | Street 2 | 2222BB | Paris
3 | Street 3 | 3333CC | London

Client

Clientnumber | Name | Gender | addressnumber
1 | Joe | M | 1
2 | Jack | M | 2
3 | Sylvia | F | 2
4 | Robert | M | 3
5 | Sarah | F | 3
6 | Stephan | M | 3

The result in the DataTable should be:

Street | Zipcode | City | Count of residents
Street 1 | 1111AA | New York | 1
Street 2 | 2222BB | Paris | 2
Street 3 | 3333CC | London | 3

I have read that it could be accomplished with filter and count but I can't figure it out how to do that.

So far I have the colums of the address table show:

$('#table').DataTable({
  ajax: {
    url: '/crm/ajax/address-data.php',
    type: 'POST'
  },     
  columns: [
    { data: 'address.street' },
    { data: 'address.zipcode' },
    { data: 'address.city' },
  ] 
});

And the address-data.php looks like this:

Editor::inst($db, 'address', 'addressnumber')
    ->field(
        Field::inst('address.street'),
        Field::inst('address.zipcode'),
        Field::inst('address.city')
    )
    ->process($_POST)
    ->json();

So far so good but how do I get the 4th column with the count of the residents of an address?

Best regards,

Arie

Answers

  • rf1234rf1234 Posts: 3,176Questions: 92Answers: 438

    You could use an Mjoin for example and count the values client side. Or you embed SQL ( COUNT(*) ) and return the result from the server.

    Here is Mjoin solution.

    Editor::inst($db, 'address', 'addressnumber')
        ->field(
            Field::inst('address.street'),
            Field::inst('address.zipcode'),
            Field::inst('address.city')
        )
        ->join(
        Mjoin::inst( 'client' )
            ->link( 'address.addressnumber', 'client.addressnumber' )
            ->fields(
                Field::inst( 'client.name' )->set( false )               
            )
        )
        ->process($_POST)
        ->json();
    
    $('#table').DataTable({
      ajax: {
        url: '/crm/ajax/address-data.php',
        type: 'POST'
      },    
      columns: [
        { data: 'address.street' },
        { data: 'address.zipcode' },
        { data: 'address.city' },
        {
            data: 'client',
            render: function (data) {
                return data.length;
            }
        }
      ]
    });
    
  • rf1234rf1234 Posts: 3,176Questions: 92Answers: 438

    This is the same using Editor's raw() method and SQL:

    Editor::inst($db, 'address', 'addressnumber')
        ->field(
            Field::inst('address.street'),
            Field::inst('address.zipcode'),
            Field::inst('address.city'),
            Field::inst('address.addressnumber AS address.residentCount') ->set( false )
                 ->getFormatter( function($val, $data, $opts) use ($db) {
                      $result = $db->raw()
                         ->bind( ':addressnumber', $val  )
                         ->exec( 'SELECT COUNT(*) AS residentCount
                                    FROM `client`
                                   WHERE addressnumber= :addressnumber' );
                       $row = $result->fetch(PDO::FETCH_ASSOC);
                       return $row["residentCount"];
                    })   
        )
        ->process($_POST)
        ->json();
    
    $('#table').DataTable({
      ajax: {
        url: '/crm/ajax/address-data.php',
        type: 'POST'
      },   
      columns: [
        { data: 'address.street' },
        { data: 'address.zipcode' },
        { data: 'address.city' },
        { data: 'address.residentCount' }
      ]
    });
    
  • arie0512arie0512 Posts: 7Questions: 2Answers: 0

    Hi rf1234,

    Tnx for getting back to me with a extended answer.

    I have try to get the Mjoin solution to work but I can't figure out what this exactly mean: Field::inst( 'client.name' )->set( false ) because I have no column named 'name' in the table. I have try to use another existing field from client like lastname but that didn't work also.

    Than I try the SQL solution and I get this workng only the load time is now very long ..... avout 2,5 minute for some 20.000 records.

    Any idea why the table loading is so long?

  • allanallan Posts: 65,042Questions: 1Answers: 10,772 Site admin

    client.name would be replaced with a field name in your m-joined table. The documentation here might help to explain things a bit.

    If you have 20k records, then yes, a separate query to get the count is going to take a long time! It would execute 20'001 queries to load the page! I'd suggest against that approach in this case. You could use server-side processing to help reduce the time, but Mjoin might be a better option for you in this case.

    There is an example of what you are trying to do here. Bit awkward that my demo data has 6 for all locations, but if you edit a person's site, you'll see the counts change.

    Allan

Sign In or Register to comment.