简体   繁体   中英

SELECT rows that are referenced less than x times in another table

In MySQL I have two tables, my reservable "weekend":

id bigint(20) unsigned,
label varchar(64),
date_start date,
max_attendees smallint(5) unsigned

And my attendees:

id bigint(20) unsigned,
name varchar(64),
email varchar(255),
weekend bigint(20) unsigned

I want to select all weekends that have attendees less than their max_attendees. This includes weekends that have 0 attendees.

Note: I also need to ignore weekend with id "1" ;

Currently, this works fine with PHP (I'm using Wordpress for mysql access), like so:

$weekends = $wpdb->get_results("SELECT * FROM $weekends_table
                                   WHERE id <> 1", ARRAY_A);

$open_weekends = array();

foreach ($weekends as $weekend) {
    $id = $weekend['id'];
    $attendees = $wpdb->get_row("SELECT COUNT(id) as attendees
                                    FROM $attendees_table
                                    WHERE weekend = $id", ARRAY_A);

    if ( $attendees['attendees'] < $weekend['max_attendees'] ) {
        $weekend['attendees'] = $attendees['attendees'];
        $open_weekends[] = $weekend;
    }
}

Shouldn't I be able to do this in MySQL without the PHP? My knowledge of MySQL doesn't extend that far. Can you suggest a query?

use the HAVING clause

This is untested, so you may have to play with it, but here's the gist:

SELECT w.*, COUNT(a.name)
FROM weekend w
LEFT JOIN attendees a
  ON w.id = a.weekend
WHERE w.id <> 1
GROUP BY w.id
HAVING (COUNT(a.name) < w.max_attendees) OR (COUNT(a.name) IS NULL)

A very simple approach would be this:

SELECT COUNT($attendees_table.id) as attendees
       attendees_table.max_attendees as maximum
FROM weekends_table, attendees_table
WHERE attendees_table.weekend = weekends_table.id
GROUP BY weekends_table.id

You could use a JOIN ON attendees_table .

This should be possible as well:

SELECT COUNT(attendees_table.id) as attendees
       weekends_table.max_attendees as maximum
FROM weekends_table, attendees_table
WHERE attendees_table.weekend = weekends_table.id
GROUP BY weekends_table.id
HAVING attendees < maximum

This is all untested. I don't have your tables or data, but it might get you going?

Ah, it didn't get what you wanted. To include zero attendees you can use a subselect:

SELECT  weekends_table.id AS weekend_id
FROM weekends_table
WHERE weekends_table.max_attendees > (SELECT COUNT(*) 
                                      FROM attendees_table 
                                      WHERE attendees_table.weekend = weekends_table.id)

It should return weekend id's where there's at least room for one more attendee. Again, completely untested, but perhaps it works?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM