Home > Software design >  how to use limit with UNION in mysql
how to use limit with UNION in mysql

Time:04-03

So, i have this problem in my hands.

I have to get multiples records from differents tables in inner join and get in a UNION or UNION ALL and use the limit to make one pagination, the following code is for get all the records and count. Here's my nemesis:

(SELECT pp.id as id, pp.*, i.name, p.name as plans_name, u.username,u.email,u.phone, DATE_ADD(pp.init_date, INTERVAL pp.avaliable_days DAY) as end_date FROM property_purchase pp
        inner join users u ON pp.users_id $username
        inner join inn_oficial i ON i.photo_id = pp.property_id
        left join plans p ON pp.plans_id = p.id
        WHERE (pp.type = 1 or pp.type = 2) 
        $where ) 
       UNION 
        (SELECT pp.id as id, pp.*, i.model as name, p.name as plans_name, u.username,u.email,u.phone, DATE_ADD(pp.init_date, INTERVAL pp.avaliable_days DAY) as end_date FROM property_purchase pp
        inner join users u ON pp.users_id $username
        inner join rent_oficial i ON i.photo_id = pp.property_id
        left join plans p ON pp.plans_id = p.id
        WHERE pp.type = 3
        $where) 
       UNION 
        (SELECT pp.id as id, pp.*, i.name, p.name as plans_name, u.username,u.email,u.phone, DATE_ADD(pp.init_date, INTERVAL pp.avaliable_days DAY) as end_date FROM property_purchase pp
        inner join users u ON pp.users_id $username
        inner join fish_pay_oficial i ON i.photo_id = pp.property_id
        left join plans p ON pp.plans_id = p.id
        WHERE pp.type = 4
        $where ) 
       UNION 
        (SELECT pp.id as id, pp.*, i.name, p.name as plans_name, u.username,u.email,u.phone, DATE_ADD(pp.init_date, INTERVAL pp.avaliable_days DAY) as end_date FROM property_purchase pp
        inner join users u ON pp.users_id $username
        inner join stores_oficial i ON i.photo_id = pp.property_id
        left join plans p ON pp.plans_id = p.id
        WHERE pp.type = 5
        $where)
       UNION
        (SELECT pp.id as id, pp.*, i.name, p.name as plans_name, u.username,u.email,u.phone, DATE_ADD(pp.init_date, INTERVAL pp.avaliable_days DAY) as end_date FROM property_purchase pp
        inner join users u ON pp.users_id $username
        inner join transfer_oficial i ON i.photo_id = pp.property_id
        inner join plans p ON pp.plans_id = p.id
        WHERE pp.type = 6
        $where)
        GROUP BY pp.id
        ORDER BY pp.id

I get this example from 13.2.9.3 UNION Clause and tried on script

When I try to run the code it gives an error

You have a syntax error in your SQL next to 'GROUP BY id ORDER BY id LIMIT 0.25' on line 1

Sorry for my horrible english, it's not my first language

CodePudding user response:

I solved kskskskks, just add the pp id column as id_p and then ordered by that

(SELECT pp.id as id_p, pp.*, i.name, p.name as plans_name, u.username,u.email,u.phone, DATE_ADD(pp.init_date, INTERVAL pp.avaliable_days DAY) as end_date FROM property_purchase pp
    inner join users u ON pp.users_id $username
    inner join inn_oficial i ON i.photo_id = pp.property_id
    left join plans p ON pp.plans_id = p.id
    WHERE (pp.type = 1 or pp.type = 2) 
    $where ) 
   UNION 
    (SELECT pp.id as id_p, pp.*, i.model as name, p.name as plans_name, u.username,u.email,u.phone, DATE_ADD(pp.init_date, INTERVAL pp.avaliable_days DAY) as end_date FROM property_purchase pp
    inner join users u ON pp.users_id $username
    inner join rent_oficial i ON i.photo_id = pp.property_id
    left join plans p ON pp.plans_id = p.id
    WHERE pp.type = 3
    $where) 
   UNION 
    (SELECT pp.id as id_p, pp.*, i.name, p.name as plans_name, u.username,u.email,u.phone, DATE_ADD(pp.init_date, INTERVAL pp.avaliable_days DAY) as end_date FROM property_purchase pp
    inner join users u ON pp.users_id $username
    inner join fish_pay_oficial i ON i.photo_id = pp.property_id
    left join plans p ON pp.plans_id = p.id
    WHERE pp.type = 4
    $where ) 
   UNION 
    (SELECT pp.id as id_p, pp.*, i.name, p.name as plans_name, u.username,u.email,u.phone, DATE_ADD(pp.init_date, INTERVAL pp.avaliable_days DAY) as end_date FROM property_purchase pp
    inner join users u ON pp.users_id $username
    inner join stores_oficial i ON i.photo_id = pp.property_id
    left join plans p ON pp.plans_id = p.id
    WHERE pp.type = 5
    $where)
   UNION
    (SELECT pp.id as id_p, pp.*, i.name, p.name as plans_name, u.username,u.email,u.phone, DATE_ADD(pp.init_date, INTERVAL pp.avaliable_days DAY) as end_date FROM property_purchase pp
    inner join users u ON pp.users_id $username
    inner join transfer_oficial i ON i.photo_id = pp.property_id
    inner join plans p ON pp.plans_id = p.id
    WHERE pp.type = 6
    $where)
    ORDER BY id_p $pagination

CodePudding user response:

LIMIT 0.25 raises my suspicion because this clause is not represented in your provided query.

That doesn't really matter because this looks like an XY Problem -- I don't see any need to use any UNION clauses or GROUP BY. You are forcing your server to do too much work by scanning whole tables multiple times, not to mention the developer eye strain of having to read such a verbose and repetitive query.

I don't know what is inside of $where, but my crystal ball tells me that it's not secure query practices. I'd want to be using a prepared statement if there are any variables being passed in.

If you need individualized control of the column values SELECTed based on the pp.type, then you can use CASE expressions in your SELECT.

I reckon your query can boil down to something like this:

SELECT pp.*,
       i.name,
       p.name AS plans_name,
       u.username,
       u.email,
       u.phone,
       DATE_ADD(pp.init_date, INTERVAL pp.avaliable_days DAY) AS end_date
FROM property_purchase pp
JOIN users             u ON pp.users_id = u.id
JOIN inn_oficial       i ON pp.property_id = i.photo_id
LEFT JOIN plans        p ON pp.plans_id = p.id
WHERE pp.user_id = ?
    AND pp.type BETWEEN 1 AND 6
    $where
ORDER BY pp.id
  • Related