Given a data set of orders, I want to be able to get the distributors ranked in the top 200 based on the total amount of sales generated such that users having the same (total sales) figure are ranked equally:
For example:
Rank
User
Total Sales
1
25944
22026.75
2
26322
19756
2
11821
19756
I have a number of tables involved here: users, categories, user_category, orders, order_items, and products.
I have been able to write a query to compute the total sales per users using all the tables i mentioned earlier but i'm not ranking users correctly at the moment
SELECT
`customer`.`referred_by` AS `user_id`,
SUM(`customer_orders`.`quantity_purchased`) AS `total_sales`
FROM
(((`users` `customer`
LEFT JOIN `users` `referrer` ON ((`customer`.`referred_by` = `referrer`.`id`)))
JOIN (SELECT
`user_category`.`user_id` AS `user_id`,
`user_category`.`category_id` AS `category_id`,
`categories`.`name` AS `category_name`
FROM
(`user_category`
JOIN `categories` ON ((`categories`.`id` = `user_category`.`category_id`)))) `user_cat` ON ((`user_cat`.`user_id` = `customer`.`id`)))
JOIN (SELECT
`orders`.`id` AS `order_id`,
`orders`.`invoice_number` AS `invoice_number`,
`orders`.`purchaser_id` AS `purchaser_id`,
`orders`.`order_date` AS `order_date`,
`items`.`quantity` AS `order_quantity`,
`items`.`product_id` AS `product_id`,
`products`.`name` AS `product_name`,
`products`.`price` AS `product_price`,
`products`.`sku` AS `product_sku`,
(`products`.`price` * `items`.`quantity`) AS `quantity_purchased`
FROM
((`orders`
JOIN `order_items` `items` ON ((`orders`.`id` = `items`.`order_id`)))
JOIN `products` ON ((`items`.`product_id` = `products`.`id`)))) `customer_orders` ON ((`customer`.`id` = `customer_orders`.`purchaser_id`)))
GROUP BY `customer`.`referred_by`
ORDER BY `total_sales` DESC
This is the data i'm working with.
Why all the sub-queries? Your server is having to do a lot more work than it needs to.
SELECT *
FROM (
SELECT
RANK() OVER (ORDER BY SUM(`p`.`price` * `oi`.`quantity`) DESC) `rank`,
`customer`.`referred_by`,
SUM(`p`.`price` * `oi`.`quantity`) `total_sales`
FROM `users` `customer`
JOIN `orders` `o` ON `customer`.`id` = `o`.`purchaser_id`
JOIN `order_items` `oi` ON `o`.`id` = `oi`.`order_id`
JOIN `products` `p` ON `oi`.`product_id` = `p`.`id`
GROUP BY `customer`.`referred_by`
ORDER BY `total_sales` DESC
) t
WHERE `rank` <= 200;
This is a really nice guide to Rank(). Well worth taking a few minutes to scroll through it and check out the examples. Breaks it out in a way easy to consume and implement.
SELECT
RANK () OVER ( ORDER BY SUM(`customer_orders`.`quantity_purchased`) DESC) AS `Rank`,
`customer`.`referred_by` AS `user_id`,
SUM(`customer_orders`.`quantity_purchased`) AS `total_sales`
FROM
(((`users` `customer`
LEFT JOIN `users` `referrer` ON ((`customer`.`referred_by` = `referrer`.`id`)))
JOIN (SELECT
`user_category`.`user_id` AS `user_id`,
`user_category`.`category_id` AS `category_id`,
`categories`.`name` AS `category_name`
FROM
(`user_category`
JOIN `categories` ON ((`categories`.`id` = `user_category`.`category_id`)))) `user_cat` ON ((`user_cat`.`user_id` = `customer`.`id`)))
JOIN (SELECT
`orders`.`id` AS `order_id`,
`orders`.`invoice_number` AS `invoice_number`,
`orders`.`purchaser_id` AS `purchaser_id`,
`orders`.`order_date` AS `order_date`,
`items`.`quantity` AS `order_quantity`,
`items`.`product_id` AS `product_id`,
`products`.`name` AS `product_name`,
`products`.`price` AS `product_price`,
`products`.`sku` AS `product_sku`,
(`products`.`price` * `items`.`quantity`) AS `quantity_purchased`
FROM
((`orders`
JOIN `order_items` `items` ON ((`orders`.`id` = `items`.`order_id`)))
JOIN `products` ON ((`items`.`product_id` = `products`.`id`)))) `customer_orders` ON ((`customer`.`id` = `customer_orders`.`purchaser_id`)))
GROUP BY `customer`.`referred_by`
ORDER BY `total_sales` DESC
Related
Hello I have this query generated by sequelize
`Orders` .*,
`OrderPriority`.`id` as `OrderPriority.ID`,
`OrderPriority`.`priority` as `OrderPriority.priority`,
`Employees`.`employee_alias` as `Employees.alias`,
`Employees`.`employee_id` as `Employees.ID` from
(
select
`Orders`.`id` as `ID`,
`Orders`.`due_date` as `dueDate`,
`Orders`.`creation_date` as `creationDate`,
`Orders`.`priority_id` as `priorityID`,
`OrderStatus`.`id` as `OrderStatus.ID`,
`OrderStatus`.`status` as `OrderStatus.status`
from
`orders` as `Orders`
inner join `statuses` as `OrderStatus` on
`Orders`.`status_id` = `OrderStatus`.`id`
where
(`Orders`.`creation_date` >= '2022-07-06 00:00:00'
and `Orders`.`creation_date` < '2022-07-14 00:00:00')
order by
`Orders`.`creation_date` desc
limit 0,
50) as `Orders`
left outer join `order_priorities` as `OrderPriority` on
`Orders`.`priorityID` = `OrderPriority`.`id`
left outer join ( `order_employees` as `Employees->OrderEmployees`
inner join `employes` as `Employees` on
`Employees`.`employee_id` = `Employees->OrderEmployees`.`employee_id`
and (`Employees->OrderEmployees`.`state` = 'Pending'
or `Employees->OrderEmployees`.`state` = 'Accepted')) on
`Orders`.`ID` = `Employees->OrderEmployees`.`order_id`
order by
`creationDate` desc;
I need to filter by null priority but the generated query has priority on the outer query if required:false which is logically wrong and the only way that I found to put the priority inside the subquery is to use required:true but this results in an inner join and I want left join in order to take the null values. Is there a way to force the include as left join inside the subquery?The nested subquery is generated because it exists a many to many relationship between Orders and Employees and limit must be applied to orders. I want to generate the following Query:
`Orders` .*,
`OrderPriority`.`id` as `OrderPriority.ID`,
`OrderPriority`.`priority` as `OrderPriority.priority`,
`Employees`.`employee_alias` as `Employees.alias`,
`Employees`.`employee_id` as `Employees.ID` from
(
select
`Orders`.`id` as `ID`,
`Orders`.`due_date` as `dueDate`,
`Orders`.`creation_date` as `creationDate`,
`Orders`.`priority_id` as `priorityID`,
`OrderStatus`.`id` as `OrderStatus.ID`,
`OrderStatus`.`status` as `OrderStatus.status`
from
`orders` as `Orders`
inner join `statuses` as `OrderStatus` on
`Orders`.`status_id` = `OrderStatus`.`id`
left outer join `order_priorities` as `OrderPriority` on
`Orders`.`priorityID` = `OrderPriority`.`id`
where
(`Orders`.`creation_date` >= '2022-07-06 00:00:00'
and `Orders`.`creation_date` < '2022-07-14 00:00:00' and `Orders`.`priorityID` is null)
order by
`Orders`.`creation_date` desc
limit 0,
50) as `Orders`
left outer join ( `order_employees` as `Employees->OrderEmployees`
inner join `employes` as `Employees` on
`Employees`.`employee_id` = `Employees->OrderEmployees`.`employee_id`
and (`Employees->OrderEmployees`.`state` = 'Pending'
or `Employees->OrderEmployees`.`state` = 'Accepted')) on
`Orders`.`ID` = `Employees->OrderEmployees`.`order_id`
order by
`creationDate` desc;
In following query I indexed every field like:
menu.id
pricelist.menu_id
vendors.id
pricelist.vendor
orders.pricelist_id
pricelist.id
users.id
orders.user_id
orders.free
pricelist.menu_id.
When I run the below query it takes much time, we have 13 million records in orders table and other table has few thousands.
SELECT
`orders`.`itusername`,
`orders`.`iturl`,
`orders`.`error_message`,
`orders`.`return` AS return1,
`orders`.`coupon`,
DATEDIFF( users.reseller_expiry, now( ) ) AS edays,
`users`.`email`,
`menu`.`menuname`,
`orders`.`error_status`,
`orders`.`auto_status`,
`vendors`.`name`,
`vendors`.`id` AS venderid,
`pricelist`.`servicename`,
`orders`.`email_order` AS paypal_order_email,
`orders`.`user_id`,
`orders`.`services_order`,
`orders`.`created_dt`,
`orders`.`id`,
`orders`.`transaction_comment`,
`orders`.`url`,
`orders`.`requireviews`,
`orders`.`youtubeviews`,
`orders`.`total_views_completed`,
`orders`.`aff`,
`orders`.`is_package`,
`orders`.`price`,
`orders`.`order_from_site`,
`orders`.`cost_per_unit_order`,
`orders`.`service_name_order`,
`orders`.`status`,
`orders`.`start_api_date`,
`orders`.`end_api_date`,
`orders`.`allow_setting`,
`orders`.`return2`,
`users`.`balance` AS user_balance
FROM
( `pricelist` )
JOIN `menu` ON `menu`.`id` = `pricelist`.`menu_id`
JOIN `vendors` ON `vendors`.`id` = `pricelist`.`vendor`
JOIN `orders` ON `orders`.`pricelist_id` = `pricelist`.`id`
JOIN `users` ON `users`.`id` = `orders`.`user_id`
WHERE
`orders`.`free` != 1
AND pricelist.menu_id = 3
ORDER BY
`orders`.`id` DESC
LIMIT 10.
.................................
The trick is to do the LIMIT before running around to 5 tables.
SELECT ...
FROM
( SELECT orders.pricelist_id AS id
FROM pricelist
JOIN `orders` ON `orders`.`pricelist_id` = `pricelist`.`id`
WHERE `orders`.`free` != 1
AND pricelist.menu_id = 3
ORDER BY `orders`.`id` DESC
LIMIT 10
) AS x
JOIN `pricelist` ON pricelist.id = x.id
JOIN `menu` ON `menu`.`id` = `pricelist`.`menu_id`
JOIN `vendors` ON `vendors`.`id` = `pricelist`.`vendor`
JOIN `orders` ON `orders`.`pricelist_id` = x.`id`
JOIN `users` ON `users`.`id` = `orders`.`user_id`
ORDER BY `orders`.`id` DESC
There is a unknown -- are the tables 1:1 or 1:many or many:1 or many:many? With the 'wrong' answers, you will get more than 10 rows, and the design is flawed.
I have a SQL Query. When I run it executes successfully, but when i was trying to create a view with the query it shows create a view with each subquery.
SOS.
SELECT `product_category_vendor_id`,
ct1.category_id,
ct1.category_name,
c1.`product_id`,
p1.product_name,
c1.`vendor_id`,
v1.vendor_name,
c1.`product_purchase_price`,
c1.product_vendor_qty,
d1.available
FROM (SELECT `product_category_vendor_id`,
a1.`product_id`,
a1.`vendor_id`,
a1.`product_purchase_price`,
b2.product_vendor_qty
FROM (SELECT `product_category_vendor_id`,
`product_id`,
`vendor_id`,
`product_purchase_price`
FROM tbl_inksand_product_category_vendor
WHERE product_category_vendor_id IN
(SELECT
Max(product_category_vendor_id) AS
`Product_Category_Vendor_Id`
FROM
tbl_inksand_product_category_vendor
WHERE (
product_category_vendor_status =
'A' )
GROUP BY product_id,
`vendor_id`
ORDER BY `product_id`))
AS a1
JOIN (SELECT `product_id`,
`vendor_id`,
Sum(`product_vendor_qty`) AS Product_Vendor_Qty
FROM tbl_inksand_product_category_vendor
GROUP BY product_id,
`vendor_id`
ORDER BY `product_id`) b2
ON a1.`product_id` = b2.`product_id`
AND a1.`vendor_id` = b2.`vendor_id`) c1
JOIN (SELECT `product_id`,
`vendor_id`,
Count(`item_id`) AS Available
FROM `tbl_inksand_item_dtls`
WHERE `product_item_status` = 'Not Sale'
GROUP BY `product_id`,
`vendor_id`) d1
ON c1.`product_id` = d1.`product_id`
AND c1.`vendor_id` = d1.`vendor_id`
JOIN tbl_inksand_vendor AS v1
ON c1.`vendor_id` = v1.`vendor_id`
JOIN tbl_inksand_product p1
ON p1.product_id = c1.`product_id`
JOIN tbl_inksand_category ct1
ON ct1.category_id = p1.category_id
Subqueries cannot be used in the FROM clause of a view.
Source: https://dev.mysql.com/doc/refman/5.0/en/view-restrictions.html
So yeah it was the right reccomendation to create seperate views.
I am writing a query
SELECT
`user_bookmarks`.`id` as `user_bookmark_id`,
`bookmark_id`,
`user_bookmarks`.`user_id`,
`bookmark_url`,
`bookmark_website`,
`bookmark_title`,
`bookmark_preview_image`,
`bookmark_popularity`,`category_id`,
`category_name`,
`pdf_txt_flag`,
`youtube_video`,
`content_preview`,
`snapshot_preview_image`,
`mode`
FROM
`user_bookmarks`
left join `bookmarks`
on `user_bookmarks`.`bookmark_id` = `bookmarks`.`id`
left join `categories`
on `user_bookmarks`.`category_id` = `categories`.`id`
WHERE
`category_id` IN(164,170,172)
LIMIT 0, 6
it is fetching first 6 bookmarks. But i want it will fetch 6 bookmarks from each category. Can we do this in mysql itself.
Please adivce..
Thanks
You can use a rank query to give a rank for each category and filter it with your desired no of records per category below query will give you 6 records from each category
SELECT t.* FROM
(SELECT
`user_bookmarks`.`id` AS `user_bookmark_id`,
`bookmark_id`,
`user_bookmarks`.`user_id`,
`bookmark_url`,
`bookmark_website`,
`bookmark_title`,
`bookmark_preview_image`,
`bookmark_popularity`,
`category_id`,
`category_name`,
`pdf_txt_flag`,
`youtube_video`,
`content_preview`,
`snapshot_preview_image`,
`mode` ,
#r:= CASE WHEN category_id = #g THEN #r+1 ELSE #r:=1 END `rank` ,
#g:=category_id
FROM
`user_bookmarks`
LEFT JOIN `bookmarks`
ON `user_bookmarks`.`bookmark_id` = `bookmarks`.`id`
LEFT JOIN `categories`
ON `user_bookmarks`.`category_id` = `categories`.`id`
JOIN (SELECT #r:=0,#g:=0) t1
WHERE `category_id` IN (164, 170, 172)
ORDER BY category_id
) t
WHERE t.rank <=6
You have to use the GROUP BY statement, but you cannot have a limit per each one of them.
I suggest you look at this question with answer in Old post and read the article mentioned in the post.
I have a query that sums a field AS a var and then uses that var in the same select to do a calculation,but it's not recognizing that var for some reason. I've tried all kinds of different ways of constructing the select, but cannot make it recognize the var!
The var in question here is the_po_cost. Any help, massively appreciated!
SELECT `orders`.`id`, accounts.account_name, orders.status, orders.order_type, DATE_FORMAT(date_issued, '%d-%m-%Y'), `cost`, SUM(po.po_cost) AS the_po_cost, `total_cost`, (orders.cost - (if null(cc.cc_cost, 0) + if null(the_po_cost, 0))) AS Margin, `users`.`email`
FROM (`orders`)JOIN `accounts` ON `accounts`.`account_id` = `orders`.`account_id`
JOIN `users` ON `users`.`id` = `orders`.`account_manager_id`
LEFT OUTER JOIN `po` ON `po`.`order_id` = `orders`.`id`
LEFT OUTER JOIN `cc` ON `cc`.`order_id` = `orders`.`id`
GROUP BY `orders`.`id`
ORDER BY `orders`.`id` desc
LIMIT 10
Need to do that sum in the math section rather than on it's own!
SELECT `orders`.`id`, accounts.account_name, orders.status, orders.order_type, DATE_FORMAT(date_issued, '%d-%m-%Y'), `cost`, `total_cost`, (orders.cost - (if null(cc.cc_cost, 0) + if null(SUM(po.po_cost), 0))) AS Margin, `users`.`email`
FROM (`orders`)JOIN `accounts` ON `accounts`.`account_id` = `orders`.`account_id`
JOIN `users` ON `users`.`id` = `orders`.`account_manager_id`
LEFT OUTER JOIN `po` ON `po`.`order_id` = `orders`.`id`
LEFT OUTER JOIN `cc` ON `cc`.`order_id` = `orders`.`id`
GROUP BY `orders`.`id`
ORDER BY `orders`.`id` desc
LIMIT 10