Using query with group_concat to loop values but show lowest price - php

I am using the query below to get all results and then then group them. It all works well. I now have multiple rows of identical data but with a different price.
How can I do the same query but get just the row with the cheapest price when all other data is identical. I have spent ages but no joy at all. Please help.
$results = $wpdb->get_results($wpdb->prepare("
SELECT *,
group_concat(date,':',SUBSTRING_INDEX(flights,'|',2),':',price,':',board,':',$tablename.id separator ',') as itemx
FROM $tablename
WHERE post_type = 'product'
GROUP BY brochure
LIMIT 20
"));

Presumably, you want something like this:
SELECT t.*,
FROM $tablename t
WHERE t.post_type = 'product' AND
t.price = (SELECT MIN(t2.price)
FROM $tablename t2
WHERE t2.post_type = 'product' AND
t2.brochure = t.brochure
);
This is at least a correctly constructed query that gets the minimum price for each brochure.

Related

How to get a response from a mysqli multi query or how do I get the number of the row sorted in descending order?

I need to run a query with sorting, to get the rating of users, and accordingly show the user his place in the leader-bord.
I found how to execute the query, but I can't figure out how to call it from the code. I get either null or a query error.
$stmAt = $mysqli->multi_query("SET #rank=0;
SELECT RANK FROM
(
SELECT #rank:=#rank+1 AS 'RANK', user_id FROM
(
SELECT score, user_id
FROM `fishing_contest` GROUP BY user_id ORDER BY score DESC
) as t1
) as t2
WHERE user_id = ?";");
$stmAt->bind_param("i", $_SESSION['id']);
$stmAt->execute();
$data = $stmAt->get_result();
$userContest = $data->fetch_assoc();
I have a solution to use a normal query and by assigning a variable and a while loop to output the position, but it is too long. So I would like to know how to use and get a response from queries of this kind?

Get data from WordPress MySQL user_meta table and my custom table

I have a custom table "orders" in which I save orders data.
| id | user_id | product
In this way, I get data from it.
$orders = $wpdb->get_results(
"
SELECT *
FROM sbgf_pl_orders
ORDER BY ID DESC
LIMIT 500
");
foreach ( $orders as $order ){
echo $order->id;
}
I want to link my request with user_meta table so that I would get orders from those users whose profile has a specific delivery method as suer meta "shippment_method".
I tried this, but this request overloads my site
$orders = $wpdb->get_results(
"
SELECT *
FROM sbgf_pl_orders, sbgf_user_meta
WHERE sbgf_user_meta.shipping_method = '1' AND sbgf_user_meta.user_id=sbgf_user_meta.user_id
ORDER BY ID DESC
LIMIT 500
");
foreach ( $orders as $order ){
echo $order->id;
}
You are not joining the tables properly :
AND sbgf_user_meta.user_id=sbgf_user_meta.user_id
This condition will always be true, and your join results in a cartesian product between users and orders having shipping method 1.
Also, you should always use explicit joins instead of old-school, implicit joins, as explained for example in this SO answer.
Finally, it is also a good practice to alias the tables in the query, and to prefix the columns with these aliases. This makes the query easier to read and maintain, and avoid ambiguity when column names conflict.
Your query should probably look like :
SELECT *
FROM sbgf_pl_orders ord
INNER JOIN sbgf_user_meta usr ON usr.shipping_method = 1 AND usr.user_id = ord.user_id
ORDER BY ord.ID DESC
LIMIT 500
#GMB thank you for the idea. I guessed how to do it right
$orders = $wpdb->get_results(
"
SELECT *
FROM sbgf_pl_orders ord
INNER JOIN sbgf_usermeta m1 ON (ord.user_id = m1.user_id AND m1.meta_value = '1'
ORDER BY ord.ID DESC
LIMIT 500
"
);

MySQL query to grab ALL rows that contain duplicate value in "slug" column

This code is looking for the rows that contain the same value in "slug" column and grouping them if they are found more than once.
UPDATED CODE:
$sql = " SELECT *,
COUNT(slug)
FROM cars
GROUP BY slug
HAVING ( COUNT(slug) > 1 )";
$q = $this->db->query($sql);
return $q;
The problem is that instead of:
blue-volkswagen-2001
blue-volkswagen-2001
red-toyota-1989
red-toyota-1989
red-toyota-1989
green-mercedes-50
green-mercedes-50
I am getting this:
blue-volkswagen-2001
red-toyota-1989
green-mercedes-50
Any idea what am I doing wrong and why only the first row is grabbed instead of all duplicates?
I have asked this question on CodeIgniter forum, but they didn't know how to do this so I can accept a custom SQL query from some SQl guru instead of Active Record, because that's probably not possible to achieve with Active Record.
You can use INNER JOIN with a subquery to achieve this.
$query = "SELECT a.*, b.total_count FROM cars a INNER JOIN (SELECT slug, count(*) as total_count FROM cars GROUP BY slug HAVING count(slug) > 1 ) b ON a.slug = b.slug WHERE b.total_count > 1";
$output = $this->db->query($query );
Do index slug column to improve performance.
This will give the output like the way you want.
Hope this helps :-)
Using subquery
SELECT * FROM `cars` WHERE slug IN ( SELECT slug FROM vehicle GROUP BY slug
HAVING ( COUNT(slug) > 1 ) )
SQLFIDDLE
SELECT MAX(slug)
FROM cars
GROUP BY slug
HAVING COUNT(slug) > 1

Codeigniter: Selecting the SUM of rows give the SUM times GROUP_CONCAT results?

I'm querying four tables (which are: resources, tag_list, resource_tags and votes) and trying to retrieve a list of resources with each list item having grouped tags and the sum of votes for that resource.
This is my current model:
$this->db->select('*');
$this->db->select('GROUP_CONCAT(DISTINCT tag SEPARATOR " | ") AS tags, SUM(vote) AS sumvotes');
$this->db->from('resources');
$this->db->join('resource_tags', 'resources.r_id = resource_tags.resource_id', 'left');
$this->db->join('tag_list', 'tag_list.t_id = resource_tags.tag_id', 'left');
$this->db->join('votes', 'votes.resource_id = resources.r_id', 'left');
$this->db->where('resources.published', '1');
$this->db->group_by('resources.r_id');
$this->db->order_by('votes.vote', 'desc');
$query = $this->db->get();
Edit: Here is the raw generated SQL
SELECT *, GROUP_CONCAT(DISTINCT tag SEPARATOR " | ") AS tags, SUM(vote) AS sumvotes
FROM (`olu_resources`)
LEFT JOIN `olu_resource_tags` ON `olu_resources`.`r_id` = `olu_resource_tags`.`resource_id`
LEFT JOIN `olu_tag_list` ON `olu_tag_list`.`t_id` = `olu_resource_tags`.`tag_id`
LEFT JOIN `olu_votes` ON `olu_votes`.`resource_id` = `olu_resources`.`r_id`
WHERE `olu_resources`.`published` = '1'
GROUP BY `olu_resources`.`r_id`
ORDER BY `olu_votes`.`vote` desc
It seems to do everything except for calculating the correct number of votes, it returns the number of votes there are multiplied by the number of tags that item has.
Does anyone know why this is happening? Or how to go about fixing this query?
Why don't you use a sub-query to get the votes?
Active Record in CI is great to use for simple queries but difficult (and slow) when you have more complex queries like yours.
It is probably all possible with Active Record though I would check the profiler first and look at the difference in speed. Last time I did something like that it made a 7 second difference.
I would try something like this:
$SQL = "SELECT *, GROUP_CONCAT(DISTINCT tag SEPARATOR ' | '),
(SELECT SUM(vote) FROM olu_votes WHERE olu_votes.resource_id = olu_resources.r_id) AS sumvotes
FROM (olu_resources)
LEFT JOIN olu_resource_tags ON olu_resources.r_id = olu_resource_tags.resource_id
LEFT JOIN olu_tag_list ON olu_tag_list.t_id = olu_resource_tags.tag_id
LEFT JOIN olu_votes ON olu_votes.resource_id = olu_resources.r_id
WHERE olu_resources.published = '1'
GROUP BY olu_resources.r_id
ORDER BY olu_votes.vote desc"
$this->db->query($SQL);
This should hopefully also resolve your problem. Let me know if this works!
if needed I'll create a test query on my own system to get you the result you want.

Returning Mysql result with COUNT( * )

I'm trying to return a count from mysql. My code is below
$number_of_options_sql = tep_db_query("SELECT COUNT( * ) FROM
(select sum(options_id) as total from products_attributes
where products_id='".$products_id."' group by options_id) as total");
$number_of_options_result = tep_db_fetch_array($number_of_options_sql);
When I run this query in Phpmyadmin, it shows the result with COUNT(*) at the table heading. I'm getting the correct result, the query works for me, I just can't print it out on the screen.
I've tried returning the value the following ways and neither print anything on the screen:
echo $number_of_options_result[COUNT( * )];
echo $number_of_options_result[total];
Use AS field_name after COUNT(*)
$number_of_options_sql = tep_db_query("SELECT COUNT(*) AS field_name FROM (select sum(options_id) as total from products_attributes where products_id='".$products_id."' group by options_id) as total");
To print:
echo $number_of_options_result['field_name'];
(Replace "field_name" with any relevant name of your choice)
Your query is assigning an alias to the table/query not the column. use this one below:
$number_of_options_sql = tep_db_query("SELECT COUNT(*) as total FROM (select sum(options_id) as total from products_attributes where products_id='".$products_id."' group by options_id) a");
$number_of_options_result = tep_db_fetch_array($number_of_options_sql);
Also looks like you want to know count of distinct options id for a product_id, I would rewrite the query as follows:
$number_of_options_sql = tep_db_query("SELECT COUNT(DISTINCT options_id) as total FROM products_attributes WHERE products_id='".$products_id."'");
Just edit your query to
SELECT COUNT(*) as count FROM ....
then it will be stored like 'count' and you can print it the $number_of_options_result[count]; way.
put in a variable "total"
$number_of_options_sql = tep_db_query("SELECT COUNT(*) as total
then it works
echo $number_of_options_result['total'];

Categories