VRP standstill query - optaplanner

What is purpose of Standstill in VRP? I am trying to understand below rule in VRP example. What is previousStandstill?
rule "distanceToPreviousStandstill"
when
$customer : Customer(previousStandstill != null, $distanceFromPreviousStandstill : distanceFromPreviousStandstill)
then
scoreHolder.addSoftConstraintMatch(kcontext, - $distanceFromPreviousStandstill);
end

previousStandstill is Vehicle or another Customer.
Ex.
ROUTE = VEHICLE(depot) -> CUSTOMER A -> CUSTOMER B -> CUSTOMER C -> CUSTOMER D
previousStandstill for CUSTOMER B is CUSTOMER A
previousStandstill for CUSTOMER A is VEHICLE
Vehicle location is the same as the location of depot.
So this rule add soft score for all distance in route except last part from CUSTOMER D to Vehicle

Related

How to aggregate in preload

So I have 3 tables borrower, avatar and loan
Borrower -> has_one avatar
Borrower -> has_many loan
Loan Controller
def list_borrowers do
query =
from(
p in Borrower,
select: p,
preload: [:avatar],
preload: [:loan] # I WANT TO AGGREGATE THIS USING COUNT
)
IO.inspect(Repo.all(query))end
This is working properly my problem is I don't know how to aggregate the loan.
I just want to know the number of all the loans of that borrower.
I am unaware of any possible way to preload the aggregate, but you might declare virtual field instead and include it into your query as:
from p in Borrower,
join: l in Loan,
on: p.id == l.borrower_id,
select: %{p | loan_count: count(l.id)}, # virtual field
preload: [:avatar]

Problems with stored procedure in DB

I have a stored procedure which picks up data of specific order (all the products which have been bought with that order) and I have implemented a grading system where each buyer can rate the products he bought. Now my problem is, when 1 buyer rates all the products he bought (lets say 3 products), and now when the next buyer comes, buys all 3 same products , and when he gets in the form for rating the products, he gets the grades of the previous guy who rated those (lets say 4,5 and 1 grade). Here is the stored procedure I use:
ALTER procedure [dbo].[hsp_Narudzbe_Detalji2]
(
#NarudzbaID int
)
as
select ns.*,p.Naziv,p.Sifra,p.Cijena,ISNULL(o.Ocjena,-1) as Ocjena
from NarudzbeStavke as ns join Proizvodi as p
on ns.ProizvodID= p.ProizvodID left join ocjene as o
on o.ProizvodID=p.ProizvodID
where ns.NarudzbaID = #NarudzbaID
As you can see, I select all the products which have been ordered for a specific order ( where ns.narudzbaid=#NarudzbaID) and I also do left join to see which products haven't been rated yet. Now I'd like to kick out the ratings of the 1st buyer so that the 2nd buyer can insert his grades also?
Can someone help me up with this?
You also have to store orderid and buyerid in ocjene table and have to join it as following:
left join
ocjene as o
on
o.ProizvodID = p.ProizvodID AND
o.buyerid = ns.[field of buyer/customer id] AND
o.NarudzbaID = ns.NarudzbaID

Assign customers to shops. Shops have maximum assigned customers

Overview:
I have shops with defined radius (20 miles). I have customers. If a customer is within 20 miles from a shop, the customer is assigned to this shop. If one customer is within 20 miles from more than 1 shop, the customer is assigned to the shop that the customer spend most money to.
The above is implemented and working fine. But now I have new requirement, I need help with. The shops now have limit of maximum number of assigned customers.
So my problem is when a customer can be assigned to two shops, and the customer is suppose to be assigned to the because of most money spend, but this shop already reached the maximum number of assigned customers. In this case the customer must be assigned to shop2
Query so far:
-- assigned all customers to all shops
INSERT INTO #assignment
SELECT cd.ap_business_id ,
cb.customer_id ,
dist.distance
FROM shops cd
CROSS JOIN customer cb
JOIN ZipDistance dist ON dist.zip1 = cd.business_zip
AND cb.zip = dist.zip2
-- If customer is assigned to more than one shop, keep the assignment to the shop that is closest to the customer
-- or to the shop where the customer spends most money. Remove other assignments.
;
WITH CTE
AS ( SELECT a.ap_business_id ,
a.customer_id ,
a.vehicle_id ,
ROUND(a.distance, 1) AS distance ,
db$.max_dealer_net_sales AS total1 ,
b$.max_dealer_net_sales AS total2 ,
ROW_NUMBER() OVER ( PARTITION BY a.customer_id ORDER BY ROUND(a.distance,
1) ASC, ISNULL(c$.max_shop_net_sales,
0) DESC, a.customer_id ) AS RN
FROM #assignment a -- total $ that given Business spend for collision parts
LEFT JOIN ( SELECT ap_business_id ,
SUM(amount) AS max_customer_net_sales
FROM customer_payments iq
WHERE iq.close_date > DATEADD(YEAR, -1,
GETDATE())
GROUP BY iq.ap_business_id
) c$ ON c$.ap_business_id = a.ap_business_id
WHERE a.customer_id IN ( SELECT vehicle_id
FROM #assignment aa
GROUP BY aa.customer_id
HAVING COUNT(*) > 1 )
)
DELETE #assignment
FROM #assignment a
JOIN CTE c ON a.ap_business_id = c.ap_business_id
AND a.customer_id = c.customer_id
AND c.RN > 1

How to specify where clause with at least x values from nested select

Suppose I have these tables:
person
id name
-- ----
1 dude
2 john
3 doe
...etc
favourite_food
personid food
-------- ------
1 apples
5 apples
5 oranges
And I want to get a list of the names of people who like at least the foods that person 5 likes. Something like below:
SELECT p.name FROM person p
LEFT JOIN favourite_food ff ON ff.personid = p.id
WHERE ff.food = (SELECT food FROM favourite_food WHERE personid = 5)
AND ff.personid <> 5;
Except I have no idea how to specify the 'at least' part. Do I have to create a temporary table or so?
SQL essentially works with sets, so it often helps to reformulate your problem strictly in terms of set theory.
"At least" could be reformulated this way:
If we look only at foods that are favourite foods of person 5, which persons have the same number of favourite foods as person 5?
SELECT name
FROM person
WHERE id IN (SELECT personid
FROM favourite_food
WHERE food IN (SELECT food
FROM favourite_food
WHERE personid = 5)
GROUP BY personid
HAVING COUNT(food) = (SELECT COUNT(food)
FROM favourite_food
WHERE personid = 5)
)
Alternatively, use this reformulation:
We do not want persons who do not like a food that person 5 likes.
Therefore, find all persons for which no food exists that is liked by person 5 but not liked by that person:
SELECT name
FROM person
WHERE NOT EXISTS (SELECT 1
FROM favourite_food AS person5_food
WHERE personid = 5
AND NOT EXISTS (SELECT 1
FROM favourite_food
WHERE personid = person.id
AND food = person5_food.food)
)
(Actually, SQL is based on the relational algebra, and the operation you want is called division.)

Return value from within a range in SQL Server 2008

I have two tables, one where it contains members & their cardnumbers, and outlet table which identifies the cardnumber ranges per outlet. I want to know which store the cardnumber the member has belongs to.
Members Table
MemberID Cardnumber FirstName LastName
1 123456123 John Doe
2 123456245 Sarah Smith
Outlets Table
OutletID OutletName StartCardNumber EndCardNumber
1 Balmain Store 123456100 123456200
2 Sydney Store 123456201 123456300
I can't think of a script which I can bring back the following information without having to
create a temp table first. Is there an easier way?
CardNumber FirstName LastName OutletName
123456123 John Doe Balmain Store
123456245 Sarah Smith Sydney Store
It's very simple. You join on a range using inequalities in addition to equalities.
SELECT
M.CardNumber,
M.FirstName,
M.LastName,
O.OutletName
FROM
dbo.Members M
INNER JOIN dbo.Outlets O
ON M.CardNumber >= O.StartCardNumber
AND M.CardNumber <= O.EndCardNumber
This is the same as M.CardNumber BETWEEN O.StartCardNumber AND O.EndCardNumber but I wanted to draw out the inclusive endpoints of your scheme using >= and <=. BETWEEN is not always suitable because very often the end value is exclusive requiring <, but not in this case.
Try this out right now online!

Resources