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,177Questions: 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,177Questions: 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,045Questions: 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

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

    because I have no column named 'name' in the table.

    Client
    Clientnumber | Name | Gender | addressnumber
    1 | Joe | M | 1

    Well, you say that you do have a column called "name" in your table but anyway ... You can take any column from your "client" table and return it from the server so that it can be counted on the client side.

Sign In or Register to comment.