How to change a query in mysql so it retrieve 30 rows randomly - mysql

I'd like to change this query in my WordPress plugin so that it retrieves 30 random rows out of 100.
$query = $wpdb->prepare("
SELECT
p.*, qq.quiz_id, qq.question_order AS order
FROM
{$wpdb->posts} p
INNER JOIN
{$wpdb->prefix}learnpress_quiz_questions qq ON p.ID = qq.question_id
WHERE
qq.quiz_id IN (" . join( ',', $format ) . ")
AND
p.post_status = %s
", $args );
I've changed it to this but it still does not work. Could any body help me ,please?
SELECT
p.*, qq.quiz_id, qq.question_order AS order
FROM
{$wpdb->posts} p
INNER JOIN
{$wpdb->prefix}learnpress_quiz_questions qq ON p.ID = qq.question_id
WHERE
qq.quiz_id IN (" . join( ',', $format ) . ")
AND
p.post_status = %s
ORDER BY
RAND() LIMIT 30

Change your sort to something like this:
order by RAND() * 30
or if you have an integer id:
order by RAND() * id

Related

SQL : get row with MIN(date)

I want to get the row with the MIN(c.date_debut), I did this, but I get a
Invalid use of group function
select distinct num_facture, s.nom, f.montant_ht, a.regle_client, a.date_reglement_effectif_client, a.type_ligne
from facture f, mission m, activite a, commande c , societe_client s
where f.activite_id = a.id and a.mission_id = m.id and m.id = c.mission_id
and m.client_id = s.id
and min(c.date_debut)
and a.type_ligne in ('Forfait','Presta')
and a.annee_id>=4
and s.nom like '%capgemini%'
group by num_facture, s.nom, f.montant_ht, a.regle_client, a.date_reglement_effectif_client, a.type_ligne
If anyone can help me on this...
Use order by and limit:
select . . .
from . . .
order by date asc
limit 1;

Speed up the query when using multiple joins in mysql

I have sql query where need to join 5 tables. I have tried this query so far.
It is working but taking long time. what can be done here to optimise following query?
$select_query = 'select ';
$select_query .= "ROUND((
6371 * ACOS(
COS(RADIANS('.$lat.')) COS(RADIANS(lat)) COS(
RADIANS(lng) - RADIANS('.$lng.')
) + SIN(RADIANS('.$lat.')) * SIN(RADIANS(lat))
)
),2) AS property_distance ,";
$select_query .= "
pro.id as id,
pro.user_id,
pro.category_id,
pro.total_price,
pro.size,
pro.lat,
pro.lng,
pro.city,
pro.city_english,
pro.created_at,
pimg.image as property_images,
pimg.property_id,
pa.property_id,
pa.category_attribute_id,
pa.is_multiple_data,
pa.attribute_value,
ca.category_id,
ca.attribute_name,
ct.category_id,
ct.category_name,
cat.attribute_id,
cat.attribute_label,
cat.locale
FROM
property pro FORCE INDEX (property_index)
left join property_images pimg on pro.id=pimg.property_id
JOIN property_attributes pa ON
pa.property_id = pro.id
left JOIN category_attributes ca ON
ca.id = pa.category_attribute_id
left JOIN category_attributes_translations cat ON
ca.id = cat.attribute_id
left JOIN categories_translation ct ON
pro.category_id = ct.category_id
WHERE pro.is_confirm='1' and pro.status='1' and pro.deal_finish='0' and cat.locale='" . $locale . "' and ct.locale='" . $locale . "'
GROUP BY pro.id HAVING property_distance<=10 ORDER by pro.id DESC";
Then finally running this query.
Please suggest me the proper way to optimise this query.
I would modify the query to rip through the property table and eliminate as many rows as possible, before doing any joins. The condition in the HAVING clause on the result of the Great Circle Distance calculation is going to require that calculation to be done on every row that isn't otherwise eliminated by the WHERE clause.
I would write a query against just the property table, something like this:
SELECT ROUND( ( 6371 * ACOS( COS(RADIANS( :lat ) )
* COS(RADIANS(pro.lat))
* COS(RADIANS(pro.lng) - RADIANS( :lng ) )
+ SIN(RADIANS( :lat ))
* SIN(RADIANS(pro.lat))
)
)
,2) AS property_distance
, pro.id
, pro.user_id
, pro.category_id
, pro.total_price
, pro.size
, pro.lat
, pro.lng
, pro.city
, pro.city_english
, pro.created_at
FROM property pro
WHERE pro.is_confirm = '1'
AND pro.status = '1'
AND pro.deal_finish = '0'
HAVING property_distance <= 10
ORDER
BY pro.id DESC
This assumes that id is unique in property table. This should be able to make effective use of index that has leading columns deal_finish,status and is_confirm to eliminate some rows from being considered.
... ON property (deal_finish,status,is_confirm,...)
Once we have that set, we can reference it as an inline view (derived table) in an outer query, and the outer query can do joins to other tables.
Note that if we have multiple matching rows in product_images and in product_attributes, doing joins to both tables will create a semi-Cartesian product, with each row from product_image matched with each row from product_attribute. i.e. 20 rows from product_image cross joined to 20 rows from product_attribute will generate a set of 400 rows.
SELECT c.*
FROM ( -- inline view query
SELECT ROUND( ( 6371 * ACOS( COS(RADIANS( :lat ) )
* COS(RADIANS(pro.lat))
* COS(RADIANS(pro.lng) - RADIANS( :lng ) )
+ SIN(RADIANS( :lat ))
* SIN(RADIANS(pro.lat))
)
)
,2) AS property_distance
, pro.id
, pro.user_id
, pro.category_id
, pro.total_price
, pro.size
, pro.lat
, pro.lng
, pro.city
, pro.city_english
, pro.created_at
FROM property pro
WHERE pro.is_confirm = '1'
AND pro.status = '1'
AND pro.deal_finish = '0'
HAVING property_distance <= 10
ORDER BY pro.id DESC
) c
LEFT
JOIN product_images pimg
ON pimg.product_id = c.id
ORDER BY c.id DESC
And now there's the whole issue of using GROUP BY to collapse rows, and expressions that are not functionally depend, beahvior with ONLY_FULL_GROUP_BY sql_mode, et al.

Wordpress get attachment url using wpdb

How can I modify this query to get the attachment url link to my custom post type.
I have tried several solution from the web but none of them are giving the expected result.
$results = $wpdb->get_results(
"SELECT ID, post_title, {$wpdb->prefix}terms.name, GROUP_CONCAT(meta_value SEPARATOR ', ') AS pictoInfos
FROM {$wpdb->prefix}posts
INNER JOIN {$wpdb->prefix}term_relationships
ON ID = {$wpdb->prefix}term_relationships.object_id
INNER JOIN {$wpdb->prefix}terms
ON {$wpdb->prefix}term_relationships.term_taxonomy_id = {$wpdb->prefix}terms.term_id
INNER JOIN {$wpdb->prefix}postmeta
ON ID = {$wpdb->prefix}postmeta.post_id
WHERE (post_type = 'recette' AND post_status = 'publish')
AND (term_taxonomy_id = {$_GET['data']['id']} AND meta_key IN ( 'kilocalorie', 'difficulte', 'nombre_de_minutes' ) )
GROUP BY ID ORDER BY ID DESC ",
ARRAY_A );

Options to update PDO Query

How i update this query?
I try get all category with more than 1 product, counting this products to show in her side, but my query is too slow (2s). How i do the same, if possible, but more faster?
SELECT
C.id, C.name, C.id_dept, C.cat_type, C.num_prod
FROM
(SELECT
C.id, C.name, C.id_dept, C.cat_type,
COALESCE((SELECT count(P.id) FROM Products P WHERE P.status = 1 AND P.promo = 1 AND P.id_cat = C.id ), 0) AS num_prod
FROM
Products_Cat C
) C
WHERE
C.num_prod > 0 AND C.cat_type = 1 AND C.id_dept = '{IDD}'
ORDER BY C.name ASC
Update PHP PDO
$sql = $db->prepare("UPDATE `Products` set `name` = :name, `id_dept` = :id_dept, `cat_type` = :cat_type WHERE status = 1 AND promo = 1);
//bind all parameters
$sql->bindParam(':name',$name);
.
.
.
$sql->execute();

limit results for wpdb query

this code displays the tags from current category only but, it gets all the tags (hundreds) so, i need to limit the number of returned results and make em random.
How to make this query get only 20 results randomly ?
/* Retrieve all tags from posts in selected categories */
$cats = array('beaches','mountains'); // Must be an array even if only one category
$cats_string = "'" . implode($cats,"','") . "'";
$sql = <<<EOSQL
SELECT DISTINCT t.*
FROM $wpdb->posts p
JOIN $wpdb->term_relationships tr ON p.ID = tr.object_id
JOIN $wpdb->term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id
AND tt.taxonomy = 'post_tag')
JOIN $wpdb->terms t ON tt.term_id = t.term_id
WHERE
p.ID IN (
SELECT p2.ID
FROM $wpdb->posts p2
JOIN $wpdb->term_relationships tr2 ON p2.ID = tr2.object_id
JOIN $wpdb->term_taxonomy tt2 ON (tr2.term_taxonomy_id = tt2.term_taxonomy_id AND tt2.taxonomy = 'category')
JOIN $wpdb->terms t2 ON (tt2.term_id = t2.term_id AND t2.name IN ($cats_string))
WHERE p2.post_type = 'post'
AND p2.post_status = 'publish'
AND p2.post_date <= NOW()
)
EOSQL;
$terms = $wpdb->get_results($sql);
// print_r($terms);
echo "<br />";
foreach ($terms as $term) {
echo "ID:$term->term_id NAME:$term->name SLUG:$term->slug<br />";
}
Thanks
You can try an ORDER BY RAND() LIMIT 20, depending on your table size this can run in decent times. See here some details on when to avoid the order by rand() logic. Like suggested, in the specified post, the other approach is to retrieve all the entries and randomly select 20 entries, in PHP rather then using mysql.