I'm working on an e-commerce project and on the client side we have two 'sort by option'
Cheapest and Expensive and for order I'm using the code below and it's ok!
$query->select([
'*',
DB::raw(
'IF(`discountPrice` IS NOT NULL, `discountPrice`, `price`) `sortPrice`',
),
])->orderBy('sortPrice', 'ASC')->paginate(15);
but I don't want the products with zero quantity to show up on the first if their price is high or low. they should be constantly on the bottom of the pagination if their quantity is 0;
any solutions?
To push all the 0 quantity products to the bottom of your result set you need to turn your quantity into a 1 or 0 (in stock / out of stock) for ordering as you do not want to order by quantity descending, as that would negate the later sorting (ASC or DESC) by price -
$query->select([
'*',
DB::raw(
'IF(`discountPrice` IS NOT NULL, `discountPrice`, `price`) `sortPrice`',
),
])->orderByRaw('IF(quantity = 0, 0, 1) DESC')
->orderBy('sortPrice', 'ASC')
->paginate(15);
Related
Question's Image
I am not able to understand how to show the details for the same person for different dates, what do I group the data by for this to happen?
I have added an Image of the question do check the link out on top, it won't let me post embedded images as I am new to stackoverflow.
I have made a sample test case tables for the problem for your convinence.
Please help out if you can.
Create Table delivery
(
deliveryId int primary key,
delivery_date date,
De_Id int ,
Pickup_time time ,
delivery_time time
);
Insert Into delivery Values (450, '2020-04-17' , 111, '8:00', '9:00');
Insert Into delivery Values (451, '2020-04-17' , 111, '21:00', '23:00');
Insert Into delivery Values (452, '2020-04-17' , 111, '11:00', '11:30');
Insert Into delivery Values (453, '2020-04-17' , 112, '2:00', '3:35');
Insert Into delivery Values (454, '2020-04-17' , 112, '4:00', '4:40');
Insert Into delivery Values (455, '2020-04-17' , 112, '5:00', '7:00');
Insert Into delivery Values (456, '2020-04-18' , 111, '9:00', '11:00');
Insert Into delivery Values (457, '2020-04-18' , 111, '8:50', '9:55');
Insert Into delivery Values (458, '2020-04-18' , 111, '7:00', '9:06');
Insert Into delivery Values (459, '2020-04-18' , 112, '2:00', '3:35');
Insert Into delivery Values (460, '2020-04-18' , 112, '4:00', '4:40');
Insert Into delivery Values (461, '2020-04-18' , 112, '5:00', '7:00');
Create Table delivery_executive
(
ID int primary key,
Name varchar(20)
);
Insert into delivery_executive Values (111, 'Abby');
Insert into delivery_executive Values (112, 'Binto');
Here's one way to solve using MySql using row_number to order each delivery by the difference between the times, then filtering out all except the highest two, then using a conditional aggregate to pivot both rows with columns for each Id
with t as (
select deliveryid, de_id, delivery_date,
Row_Number() over(partition by delivery_date, de_id order by subtime(delivery_time,Pickup_time) desc)rn
from delivery
)
select e.Name, t.delivery_date,
Max(case when rn=1 then t.deliveryid end) FirstDeliveryId, Max(case when rn=2 then t.deliveryid end) SecondDeliveryId
from t
join delivery_executive e on e.id=t.de_id
where rn<=2
group by t.delivery_date, e.Name
How max and case help.
It helps to work through in stages. So firstly if we start with just what the CTE (the with t as ) element returns for the sample data, we see 12 rows - 6 for each date - each with 3 rows per de_id and a row number rn ordered 1-3 against each group with 1 having the longest time between the pickup and delivery times and 3 the shortest.
If we just look at select * from t where rn<=2, that naturally removes the the rows where rn=3 and we're left with the data we want, the two longest delivery time periods for each date, for each executive.
The desired output is to have just two rows per each executive, one for each date, and the two IDs to be in two columns.
Looking at case first, we can add two new columns as the result of a case expression,
case when rn=1 then t.deliveryId end,
case when rn=2 then t.deliveryId end
The first case will have a value only where rn=1 likewise the second case will have a value only where rn=2 (by default without an else it returns NULL on all other non-matched cases).
So now we have our First and Second Id values but they are still split over two rows.
The other values on each pair of rows (rn=1 and rn=2), are the same in each case, being the same delivery_date and the same de_id, so this is now where we can aggregate the rows together.
The final selected columns are the de_id and delivery_date and we want to group by these - ie all the values that are the same are condensed onto a single row provided the columns that we do not group by are aggregated in some way.
The most common aggregation would be sum, for example if we were only selecting the row number column we could sum(rn) and the result would be 3 for each aggregated group (1+2). However using max it will return the maximum value for each group of rows, and since we only have either a value (deliveryId) or NULL, it returns the deliveryId.
Therefore we wrap each case expression with a max() function, group by the remaining columns and the result is the grouped columns occupy a single row in each case since the aggregate of the case expressions also returns 1 row.
Fiddle here
I am trying to return the result of an ordered form query (ascending or descending), I know it is done using order: ['columnName', sort order (ASC / DESC)], I have done well when I am only sorting on base to a single column, but suppose I have a table with these columns:
product_id, price, offer_price, offer, description
and I want to sort by price or by offer_price (the offer_price column depends on the offer column, that is, I am interested in the offer_price only if the offer column has a value of 1 which indicates that this product is really on sale).
How could I do so that the results are returned to me ordered, by price or by price_offer, that is, if a product is on sale, I have to take into account the price_offer at the time of ordering, and if it is not on sale then I should take the normal price.
For example:
Product1: product_id = 1, price = 9,000, offer_price = 8,500, offer = 1, description: 'yy'
Product2: product_id = 2, price = 2,000, offer_price = 500, offer = 0, description: 'bbb'
Product3: product_id = 3, price = 1,500, offer_price = 1,000, offer = 1, description: 'ccccc'
the query result in ascending order should be: product3, product2, product1. since product3 is on sale and is the lowest price of all (1,000), product 2 is the following (this has a price_offer = 500 but is not on sale, so the normal price is taken (2,000), and finally the product3 (8,500)).
How could I achieve this using Sequelize? I can't find something to help me with the documentation.
You can use MySQL IF function like this:
order: [sequelize.literal('(IF(offer = 1, offer_price, price))'), sort order (ASC / DESC)]
I am trying to get sum of all rows with multiply two column values with where condition but getting some error of mysql. After try some example i achieve my result but i don't know that is right way or not:
Table: store_stocks
i just want to count the stock qty with amount multiply with qty according to with VAT, with non VAT and total stock.
I just created that query:
SELECT sum(qty*sale_price) as total_stock,
(select sum(qty*sale_price) from store_stocks where vat_status = 0 and store_id = 8) as non_vat_stock,
(select sum(qty*sale_price) from store_stocks where vat_status = 1 and store_id = 8) as with_vat_stock
FROM `store_stocks` where store_id = 8 group by store_id
and its showing result:
can any one tell me is there any another way to achieve this, because i think that's query is little bit complicated, each time i am using where in sub query and i also have to implement this query in laravel eloquent.
You do not need subqueries, you can use a condition within the sum() to make it summarise the specific records only:
SELECT sum(qty*sale_price) as total_stock,
sum(if(vat_status = 0, qty*sale_price, 0)) as non_vat_stock,
sum(if(vat_status = 1, qty*sale_price, 0)) as with_vat_stock
FROM `store_stocks` where store_id = 8 group by store_id
You can use a case expression instead of the if() function as well.
Consider the following query:
$query = "
SELECT a_orders.id, a_orders.billing,
SUM(a_order_rows.quant_refunded*a_order_rows.price*((100-a_orders.discount)*.01)) as refund_total,
SUM(a_order_rows.quant*a_order_rows.price*((100-a_orders.discount)*.01)) as order_total
FROM a_order_rows JOIN a_orders
ON a_order_rows.order_id = a_orders.id
WHERE a_order_rows.quant_refunded > 0
GROUP BY a_orders.id, a_orders.billing
ORDER BY a_orders.id DESC
LIMIT 50";
The two uses of SUM() are attempting to aggregate the order total and the total amount that has been refunded. They are coming out correctly when when the quant_refunded field is not 0... for example take this data (excluding primary key, item_id for simplicity's sake, assuming each row is a unique item):
Table: a_order_rows
Fields: order_id, quant, quant_refunded
1, 1, 1
1, 2, 1
2, 1, 1
2, 1, 0
In the case of "order 1" the two aggregations are different and behave as expected. But for "order 2" the two numbers are coming out the same - both numbers are what I am expecting refund_total to be. It appears that the row with "0" in quant_refunded is being excluded from the order_total aggregation.
Hopefully this is explained thoroughly enough. Please let me know if you need more info and I will revise. THANKS!
$query = "
SELECT a_orders.id, a_orders.billing,
SUM(a_order_rows.quant_refunded*a_order_rows.price*((100-a_orders.discount)*.01)) as refund_total,
SUM(a_order_rows.quant*a_order_rows.price*((100-a_orders.discount)*.01)) as order_total
FROM a_order_rows JOIN a_orders
ON a_order_rows.order_id = a_orders.id
GROUP BY a_orders.id, a_orders.billing
HAVING MAX(a_order_rows.quant_refunded) > 0
ORDER BY a_orders.id DESC
LIMIT 50";
Change that to a HAVING clause. If any quant_refunded rows are > 0, the HAVING MAX will retain it.
I want to create a table [Top Stores] that has 10 most active stores in terms of quantity of product sold. Each store sells 3 products. I just need to add the quantity sold for each product to arrive at StoreSale. The problem is when there is no sale for a product, the quantity value is left blank and not 0. I try to change the blank to 0 by the isnull tests. Please point out the error in my code below:
SELECT top 10 StoreName, StoreSale = (iif (isnull(Product1), 0, Product1) + iif (isnull(Product2), 0, Product2) + iif (isnull(Product3), 0, Product3)) INTO [Top Stores]
FROM SaleTable ORDER BY StoreSale DESC;
Two things:
if you use =, you will be doing an equality test, you can't have an assignment like that in SQL.
You will need to name your calculated result AS StoreSale instead.
Use Nz() to get a 0.00 when the field value is NULL
Result:
SELECT TOP 10 StoreName,
Nz(product1) + Nz(Product2) + Nz(Product3) AS StoreSale
INTO [Top Stores]
FROM SaleTable
ORDER BY StoreSale DESC;