DELETE FROM wp_postmeta WHERE meta_id IN ( SELECT meta_id FROM ( -- This query will return a list of all the meta rows that are duplicates and -- that should be removed SELECT PM.meta_id ,PM.meta_key ,PM.post_id ,meta_duplicates.meta_id_to_keep ,meta_duplicates.duplicates_count FROM wp_postmeta PM JOIN ( SELECT post_id ,meta_key ,min(meta_id) as meta_id_to_keep ,count(meta_key) as duplicates_count FROM wp_postmeta WHERE (meta_key like '%_base_currency%') GROUP BY post_id, meta_key HAVING duplicates_count > 1 ) AS meta_duplicates ON (meta_duplicates.post_id = PM.post_id) AND (meta_duplicates.meta_key = PM.meta_key) -- This clause filters out the meta rows that we want to keep WHERE -- If you used MIN() above, you should check for "(PM.meta_id > meta_duplicates.meta_id_to_keep)" -- If you used MAX() above, you should check for "(PM.meta_id < meta_duplicates.meta_id_to_keep)" (PM.meta_id > meta_duplicates.meta_id_to_keep) ) AS duplicates_to_remove )