简体   繁体   中英

mySQL two tables LEFT JOIN on multiple NULLS

I have a question regarding a two table join. In this case Table1 (booking table) and Table2 (Booking Entries).

I need a query to get all the rows from Table1 WHERE the member_id in Table2 (exists only here not in table1) and Vip_id in BOTH tables can be searched.

SELECT vb.* , DATE_FORMAT(vb.bookingdate, '%W %D %M') bookingdate, DATE_FORMAT(vb.bookingrsvp, '%W %D %M') bookingrsvp, concat(sl.state, ' - ', sl.store) store,  sl.ADD1, sl.ADD2, sl.SUBURB, sl.PHONE , ve.vip_entry_leadid
FROM vip_booking vb 
INNER JOIN  storelocator sl  ON (vb.storeid = sl.id )
LEFT JOIN vip_entries ve ON (vb.vipid = ve.vip_id AND ve.vip_entry_leadid = '" . $_GET["leadid"] . "')
WHERE vb.vipid = " . $_GET["vipid"] . " 
  AND DATE(vb.bookingdate) >= CURDATE()
  AND ve.vip_entry_leadid IS NULL
  AND ve.vip_id IS NULL
GROUP BY vb.storeid ORDER BY sl.state, sl.store

Basically what I am trying to achieve here is select ALL bookings from ALL Stores part of a particular VIP EVENT that the CURRENT LOGGED IN USER hasn't already had an entry too? If it was a single field ie. vip_entries.vip_id = vip_booking.vipid THEN that would be okm however a user can be in the entries table multiple times provided that it is a DIFFERENT event?

The above query works however I don't know if I have written it correctly as I would like to use joins and avoid sub-queries.

  1. The above query works however I don't know if I have written it correctly

Unfortunately, while preceding SQL works in MySQL, your query is not valid in ANSI SQL. Only GROUP BY column and aggregation function can be SELECTed

  1. I would like to use joins and avoid sub-queries.

As far as I know without sub-queries, you can only fetch vb.storeid as follows

SELECT vb.storeid
FROM vip_booking vb 
INNER JOIN  storelocator sl ON (vb.storeid = sl.id )
LEFT JOIN vip_entries ve ON (vb.vipid = ve.vip_id AND ve.vip_entry_leadid = '$leadid')
WHERE vb.vipid = $vipid
  AND DATE(vb.bookingdate) >= CURDATE()
  AND ve.vip_entry_leadid IS NULL
  AND ve.vip_id IS NULL
GROUP BY vb.storeid;

Proper SQL with sub-queries:

In my opinion Following query is formal SQL for what you want.

SELECT 
    vb.*,
    DATE_FORMAT(vb.bookingdate, '%W %D %M') bookingdate,
    DATE_FORMAT(vb.bookingrsvp, '%W %D %M') bookingrsvp,
    CONCAT(sl.state, ' - ', sl.store) store, 
    sl.ADD1, sl.ADD2, sl.SUBURB, sl.PHONE , ve.vip_entry_leadid
FROM 
    (SELECT DISTINCT 
         vb.storeid
     FROM 
         vip_booking vb 
     LEFT JOIN 
         vip_entries ve ON (vb.vipid = ve.vip_id AND ve.vip_entry_leadid = '" . $_GET["leadid"] . "'
     WHERE 
         vb.vipid = " . $_GET["vipid"] . "
         AND DATE(vb.bookingdate) >= CURDATE()
         AND ve.vip_entry_leadid IS NULL
         AND ve.vip_id IS NULL) x 
INNER JOIN 
    storelocator sl ON (x.storeid = sl.id)
ORDER BY 
    sl.state, sl.store;

Can you post some sample data in the question please.

Your query appears to do a LEFT JOIN on vip_entries, and then checks for NULL in 2 fields to ensure no record is found (might be better to check the unique id field of vip_entries, if one exists). But you then bring back the value vip_entries.vip_entry_leadid which will always be null.

Further you are using GROUP BY store_id. This will bring back one row per store_id, but the other values will be from an undefined row for that store_id (in most databases this would fail). I suspect looking at your description you actually want to bring back one row per event / store id (which is probably a unique combination) in which case it would seem you do not need the GROUP BY.

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