retrieve top sellers from single table in mysql.? - php

I want to retrieve data from mysql of my client affiliated bestsellers for that i have table which store every order id and it's seller id also with amount of it,
table contains same name sellers so now how can i get select data in sequence of first show seller who num of rows are more and keep do it in desc order.
select DISTINCT MAX(reseller_id) FROM affilated_comission
here is mysql query i am using which is only showing one result i want it also shows who are maximum after top 1.

Something like this should do it.
SELECT
seller_id,
COUNT(volume) AS volume
FROM
table
GROUP BY
seller_id
HAVING
COUNT(volume) >= 10
ORDER BY
volume DESC

Related

Combine multiple 'orders' from mysql table and display total price?

I'm working on a panel to show all orders from our e-commerce site and the way I have the orders set up is to have a row for each order referring to the customer id.
I'm working on showing all open orders on our back-end however the rows are showing multiple rows for the same order if (so if the orderID is 18, and the order has 2 items ordered there a 2 rows all the with the orderID of 18).
I'll include some screenshots below so you have an idea of what's happening.
This is my sql statement to show all open orders:
function GetAllOpenOrders (){
global $conn;
$sql = "SELECT * FROM customer_orders LEFT JOIN ordered_products ON ordered_products.custOrderID=customer_orders.custOrderID WHERE customer_orders.orderOpen=1";
return $result = $conn->query($sql);
}
So again, I want to combine the orders with multiple products and display the total price in the open orders screen.
You need an aggregate query to display the total. Something like:
SELECT sum(prod.totalPrice) as TotalPrice
FROM customer_orders
LEFT JOIN ordered_products ON ordered_products.custOrderID=customer_orders.custOrderID
WHERE customer_orders.orderOpen=1
group by customer_orders.custOrderID
I don't have your database to test that query but that should point you in the right direction.
You need a sub-query where you SUM the order totals and then aggregate. You also can't add the "product ID" to your query otherwise it will by definition break it down into rows for each product ordered.
For example
select
customer_order_id,
sum(product_total_price) as order_total
from
(select
customer_order_id,
product_id,
product_total_price
from table
group by 1,2,3)
group by 1
If you're looking to show the names of the products ordered in your 1 row, I suggest using a CONCAT function for the product names (so it's all in one field) and then you'll have the total in 1 row.

sum row content with matching columns

Yes yes, I know. The title is stupid and hard to understand.
Question:
There's a DB1 and a DB2.
DB1 has columns called id and price. id is a unique number for each item like 301 and so on. There's only one of each id in this DB.
DB2 contains a column named id and one named price. This DB has the duty of collecting data about each id ( item ) via a php script.
This means multiple rows with the same unique id.
a picture to demonstrate:
What i'm trying to do:
a script that querys an id ( matches the id with another table ) and sums up all the price columns with the same id.
I understand innerjoin
SELECT db1.id, db2.price
FROM db1
INNER JOIN db2
ON db1.id=db2.id;
but I want to sum all db2.price rows before showing. What can I do?
What you want is this:
(I guess you want to show db1.price too (or other fields from db1, otherwise there is no meaning have this join)
SELECT db1.id, db1.price, db2s.price -- rest of db1 fields here
FROM db1
INNER JOIN (select id, sum(price) price from db2 group by id) as db2s
ON db1.id=db2s.id;
SQLFIDDLE
I don't think you need a join for that. It should be enough to just do:
SELECT id, sum(price) as price_sum FROM db2 GROUP BY id
This should give you 2 columns:
id of the price
sum of all prices for given price ID

Using mysql statement to join tables and return maximum values instead of PHP maths

In PHP with MySQL I am trying to write queries to pull certain required reports with Joined Tables.I have read though so many SQL scripting manuals, and would normally do this type of thing by pulling filtered records from db tables into PHP, and doing the math gymnastics there. Unfortunately this is inefficient so I am looking for the right SQL query to point me in the right direction. This is my situation.
I have mysql tables: events and payments, they are linked by a single ID column (events.event_id = payments.payment_event_id)
I need to get a recordset containing only the 5 events with the most associated payments. Then I would like a result array containing this original event detail arrays along with an integer which is their ticket payment count.
Ideally the result array structure would look like this:
$result_events--
|0||0|payment count(53)
|0||1|$full event array
|1||0|Payment Count (34)
|1||1|$full event array
EDIT:
After talking to people I thought I would spell out what I am after. I need a 2 column resultset, left column is event_id (from events table) and right hand column is total amount of payments for that event (ie the number of 'payment' rows which match this event id. So out of huge random tables of events and payments, I would like to be left with one like this:
| Event_id | total Payments |
but ordered by the payment column. I know I'm asking the earth :)
If you want to get the 5 most common payments for an event and get just those 5 details, you can do a subquery to get the event_ids where you group the payment_event_ids, then order the count descending top to bottom and take the top 5 results.
Then you take those ID's and get the event details that match those ids
SELECT
*
FROM
events
WHERE
event_id IN (
SELECT
payment_event_id
FROM
payments
GROUP BY payment_event_id
ORDER BY count(*) DESC
LIMIT 5
);
Optionally you can also get all the payment details with a join, but you'll get more than 5 rows returned this way
SELECT
*
FROM
events
JOIN
payments
ON
events.event_id = payments.payment_event_id
WHERE
events.event_id IN (
SELECT
payment_event_id
FROM
payments
GROUP BY payment_event_id
ORDER BY count(*) DESC
LIMIT 5
);
Simple query, only thing left for you to do is select the columnnames you need from both tables:
$q = "SELECT events.columname, payments.columnname FROM events
INNER JOIN payments ON events.event_id = payments.payment_event_id
ORDER BY payments.payment_count DESC
LIMIT 5";

Showing users who liked an item in an item list

This is an issue that I've deemed impractical to implement but I would like to get some feedback to confirm.
I have a product and users database, where users can like products, the like data is stored in a reference table with just pid and uid.
The client request is to show 3 users who have liked every product in the product listing.
The problem is, its not possible to get this data in one query for the product listing,
How I once implemented and subsequently un-implemented it was to perform a request for the users who have liked the products during the loop through the product list.
ie.
foreach($prods as $row):
$likers = $this->model->get_likers($row->id);
endforeach;
That works, but obviously results in not only super slow product listings, and also creates a big strain on the database/cpu.
The final solution that was implemented was to only show the latest user who has liked it (this can be gotten from a join in the products list query) and have a link showing how many people have liked, and upon clicking on it, opens a ajax list of likers.
So my question is, is there actually a technique to show likers on the product list, or is it simply not possible to execute practically? I notice actually for most social media sites, they do not show all likers on the listings, and do employ the 'click to see likers' method. However, they do show comments per items on the listing, and this is actually involves the same problem doesn't it?
Edit: mock up attached on the desired outcome. there would be 30 products per page.
By reading your comment reply to Alex.Ritna ,yes you can get the x no. of results with per group ,using GROUP_CONCAT() and the SUBSTRING_INDEX() it will show the likers seperated by comma or whatever separator you specified in the query (i have used ||).ORDER BY clause can be used in group_concat function.As there is no schema information is available so i assume you have one product table one user table and a junction table that maintains the relation of user and product.In the substring function i have used x=3
SELECT p.*,
COUNT(*) total_likes,
SUBSTRING_INDEX(
GROUP_CONCAT( CONCAT(u.firstname,' ',u.lastname) ORDER BY some_column DESC SEPARATOR '||'),
'||',3) x_no_of_likers
FROM product p
LEFT JOIN junction_table jt ON(p.id=jt.product_id)
INNER JOIN users u ON(u.id=jt.user_id)
GROUP BY p.id
Fiddle
Now at your application level you just have to loop through the products and split the x_no_of_likers by separator you the likers per product
foreach($prods as $row):
$likers=explode('||',$row['x_no_of_likers']);
$total_likes= $row['total_likes'];
foreach($likers as $user):
....
endforeach;
endforeach;
Note there is a default 1024 character limit set on GROUP_CONCAT() but you can also increase it by following the GROUP_CONCAT() manual
Edit from comments This is another way how to get n results per group, from this you can get all the fields from your user table i have used some variables to get the rank for product group ,used subquery for junction_table to get the rank and in outer select i have filtered records with this rank using HAVING jt.user_rank <=3 so it will give three users records per product ,i have also used subquery for products (SELECT * FROM product LIMIT 30 ) so the first 30 groups will have 3 results for each,for below query limit cannot be used at the end so i have used in the subquery
SELECT p.id,p.title,u.firstname,u.lastname,u.thumbnail,jt.user_rank
FROM
(SELECT * FROM `product` LIMIT 30 ) p
LEFT JOIN
( SELECT j.*,
#current_rank:= CASE WHEN #current_rank = product_id THEN #user_rank:=#user_rank +1 ELSE #user_rank:=1 END user_rank,
#current_rank:=product_id
FROM `junction_table` j ,
(SELECT #user_rank:=0,#current_rank:=0) r
ORDER BY product_id
) jt ON(jt.product_id = p.id)
LEFT JOIN `users` u ON (jt.`user_id` = u.`id`)
HAVING jt.user_rank <=3
ORDER BY p.id
Fiddle n results per group
You should be able to get a list of all users that have liked all products with this sql.
select uid,
count(pid) as liked_products
from product_user
group by uid
having liked_products = (select count(1) from products);
But as data grows this query gets slow. Better then to maintain a table with like counts that is maintained through a trigger or separately. On every like/dislike the counter is updated. This makes it easy to show the number of likes for each product. Then if the actual users that liked that product is wanted do a separate call (on user interaction) that fetches the specific likes for one product). Don't do this for all products on a page until actually requested.
I am assuming the size of both these tables is non-trivially large. You should create a new table (say LastThreeLikes), where the columns would be pid,uid_1,uid_2 and uid_3, indexed by pid. Also, add a column to your product table called numLikes.
For each "like" that you enter into your reference table, create a trigger that also populates this LastThreeLikes table if the numLikes is less than 3. You can choose to randomly update one of the values anyway if you want to show new users once in a while.
While displaying a product, simply fetch the uids from this table and display them back.
Note that you also need to maintain a trigger for the "Unlike" action (if there is any) to re-populate the LastThreeLikes table with a new user id.
Problem
The problem is the volume of data. From the point of view that you need two integer value as a answer you should forget about building a heavy query from your n<->n relations table.
Solution
Generates a storable representation using the file_put_contents() with append option each time a user likes a product. I don't have enough room to write the class in here.
public function export($file);
3D array format
array[product][line][user]
Example:
$likes[1293][1][456]=1;
$likes[82][2][656]=1;
$likes[65][3][456]=1;
.
.
.
Number of users who like this particular product:
$number_users_like_this_product = count($likes[$idProduct]);
All idUser who like this particular product:
$users_like_this_product = count($likes[$idProduct][$n]);
All likes
$all_likes = count($likes);
Deleting a like
This loop will unset the only line where $idProduct and $IdUser you want. Since all the variables are unsigned integer it is very fast.
for($n=1, $n <= count($likes[$idProduct]), $n++)
{
unset($likes[$idProduct][$n][$idUser]);
}
Conclusion
Get all likes will be easy as:
include('likes.php');
P.S If you want to give a try i will be glad to optimize my stuff and share it. I've created the class in 2012.

Adding a column to SQL result with AVG from another column in another table based on a condition

Im working on a report in PHP where i have to display the top results for average score for students based on condition for career, status and period, plus dinamic results... The average comes from another table.
Tables: cllg_student_assign. This table has an ID, which is referenced in table cllg_student_assign_course, which has a column SCORE_ACCU. I need to put together the row from cllg_student_assign with the AVG() of SCORE_ACCU from cllg_student_assign_course where FK_ASSIGN=cllg_student_assign.ID.
Im trying this:
SELECT *
FROM cllg_student_assign
LEFT JOIN (SELECT a.FK_ASSIGN, AVG(a.SCORE_ACCU) as SCORE
FROM cllg_student_assign_course as a, cllg_student_assign as b
WHERE b.ID=a.FK_ASSIGN) as score_table
ON cllg_student_assign.ID=score_table.FK_ASSIGN
WHERE STATUS=1
ORDER BY SCORE DESC
Im getting the rows, but i get the average of the whole SCORE_ACCU column in the table, and it puts it only on 1 record... I need each row to have a colum SCORE with its own AVG pulled from the other table.
I have worked with SQL before, but only basic stuff...
Help!

Categories