Prestashop / SQL Query from SQL Database - mysql

I am trying to create a query that returns the firstname, lastname, email and key_value for each order of a certain product (id 49) but I can't quite configure the SQL query correctly to get each key for each customer.
SELECT C.email,
C.firstname,
C.lastname,
K.key_value
FROM ps_customer C
INNER JOIN ps_orders O on C.id_customer = O.id_customer
INNER JOIN ps_order_detail OD on O.id_order = OD.id_order
INNER JOIN ps_keymanager OD on O.id_order = OD.id_order
WHERE OD.product_id =49

you could try this.. But!.
I've no idea what the ps_keymanager is, but if your using it
im sure you can fit into the query below.. ;)
SELECT O.reference AS ORDERREF, C.firstname, C.lastname, C.email AS Email
FROM ps_customer C
INNER JOIN ps_orders O on C.id_customer = O.id_customer
INNER JOIN ps_order_detail OD on O.id_order = OD.id_order
WHERE OD.product_id = 846
This will list
Order Reference | Firstname | Surname | Email
WHERE product_id = (in my case 846)

I share the consultation that I use to obtain different information from the client, by order id :
SELECT pod.id_order, c.id_customer,
CONCAT(c.firstname, c.lastname) AS client,
c.firstname, c.lastname, pa.address1, pa.address2,
pa.city, pa.id_country,c.email, pa.postcode, pa.phone_mobile,
pa.phone, pc.iso_code AS country
FROM ps_orders po
LEFT JOIN ps_order_detail pod ON (po.id_order = pod.id_order)
LEFT JOIN ps_product pp ON (pod.product_id = pp.id_product)
LEFT JOIN ps_customer c ON (c.id_customer = po.id_customer)
LEFT JOIN ps_address pa ON (pa.id_customer = c.id_customer)
LEFT JOIN ps_country pc ON (pc.id_country = pa.id_country)
WHERE pod.id_order = 34549
You can add or remove the columns you need in your sql query.

Related

MYSQL Subquery -

created this query but all the customers in the table are not showing up, i want all customers to show in the query even with any null values.there are 26 customers in the customer table but only 12 show when i run the query.
SELECT c.CID, CONCAT(c.FirstName, ' ', c.LastName) AS 'Customer Name',
c.Email, o.OrderDate, o.OrderStatus, o.DeliveryDate, a.AppetizerName, o.AppetizerQuantity,
p.PizzaName, p.PizzaSize, o.PizzaQuantity, pa.PastaName, o.PastaQuantity,
s.SandwichName, o.SandwichQuantity, d.DessertName, o.DessertQuantity,
dr.DrinkName, o.DrinksQuantity, o.TotalPrice
FROM
customer AS c
JOIN
orders AS o ON c.CID = o.CID
INNER JOIN
appetizer AS a ON a.AppetizerID = o.AppetizerID
INNER JOIN
pizza AS p ON p.PizzaID = o.PizzaID
INNER JOIN
pasta AS pa ON pa.PastaID = o.PastaID
INNER JOIN
sandwiches AS s ON s.SandwichID = o.SandwichID
INNER JOIN
dessert AS d ON d.DessertID = o.DessertID
INNER JOIN
drinks AS dr ON dr.DrinkID = o.DrinkID
GROUP BY c.FirstName, c.LastName;
Your issue is that you're using inner joins. These drop null values. If you replace each of your inner joins with left joins, your query should return all 26 customers.

Convert query with exists to joins

I want to convert this query in such a way so it does not have any 'exists' and uses only simple joins.
select t.Teacher_id, t.Teacher_name, a.marks, a.grade_ID
from Grades a
left join students s on a.student_ID = s.student_ID
left join Teachers t on t.Teacher_ID = s.Teacher_ID
where 1=1 and t.Teacher_id = 1807600
and exists(
select p.Payment_ID from payments p
inner join lookups l on (l.lookup_id = p.status_id and l.lookup_key in ('condition1','condition2'))
where p.student_ID = a.student_ID
)
I tried something like:
select t.Teacher_id, t.Teacher_name, a.marks, a.grade_ID
from Grades a
left join students s on a.student_ID = s.student_ID
left join Teachers t on t.Teacher_ID = s.Teacher_ID
inner join payments p on p.student_ID = a.student_ID
inner join lookups l on (l.lookup_id = p.status_id and l.lookup_key in ('condition1','condition2'))
where 1=1 and t.Teacher_id = 1807600
But I'm not getting the right results. Can you please help. Thanks.
I suppose you could use group by, but this restricts the maintainability of the script for the simple sake of not using EXISTS().
select t.Teacher_id, t.Teacher_name, a.marks, a.grade_ID
from Grades a
left join students s on a.student_ID = s.student_ID
left join Teachers t on t.Teacher_ID = s.Teacher_ID
inner join payments p on p.student_ID = a.student_ID
inner join lookups l on (l.lookup_id = p.status_id and l.lookup_key in ('condition1','condition2'))
where t.Teacher_id = 1807600
group by t.Teacher_id, t.Teacher_name, a.marks, a.grade_ID

Select an sql field and don't show an specific word of the selection

When this query returns me the "Center" register, there is a word at all the fields with the same name that i don't want to display. I could make it via PHP but I need to use it on the db.
Basics I know, but i haven't done sql for a long time
SELECT
o.id_order,
o.reference AS Ref,
c.firstname AS Name,
c.lastname AS Last Name,
pl.`name` AS Center,
od.product_name AS Product,
od.product_quantity AS Quant,
ROUND(od.product_price * 1.21,2) AS Price,
o.date_add AS `Date`
FROM ps_orders AS o
INNER JOIN ps_order_detail AS od ON od.id_order = o.id_order
INNER JOIN ps_customer AS c ON c.id_customer = o.id_customer
INNER JOIN ps_product_lang AS pl ON pl.id_product = od.product_id
WHERE pl.id_lang = 1
ORDER BY od.id_order_detail DESC
When this returns me Center data, all fields have the preposition "The" in front, returning something like:
Center
The Odoo Team Center
The Dev house
Then I need to show something like
Center
Odoo Team Center
Dev house
You can use REPLACE:
SELECT
o.id_order,
o.reference AS Ref,
c.firstname AS Name,
c.lastname AS Last Name,
REPLACE(pl.`name`,"The ","") AS Center,
od.product_name AS Product,
od.product_quantity AS Quant,
ROUND(od.product_price * 1.21,2) AS Price,
o.date_add AS `Date`
FROM ps_orders AS o
INNER JOIN ps_order_detail AS od ON od.id_order = o.id_order
INNER JOIN ps_customer AS c ON c.id_customer = o.id_customer
INNER JOIN ps_product_lang AS pl ON pl.id_product = od.product_id
WHERE pl.id_lang = 1
ORDER BY od.id_order_detail DESC
Documentation: https://dev.mysql.com/doc/refman/5.7/en/replace.html
Demo: http://sqlfiddle.com/#!9/a5640/91
Something like this should work if you always wants to remove the first four chars:
SELECT SUBSTRING(center, 4, LENGTH(center)-3) FROM YOURTABLE;

Group by id having max(date_field)

To build a report, I must select some information on the last transaction status of all my customers. Until now, this is what I got:
SELECT c.firstname, c.lastname, d.product_name, o.payment, s.name, h.date_add
FROM ps_orders o
INNER JOIN ps_order_detail d ON d.id_order = o.id_order
INNER JOIN ps_customer c ON c.id_customer = o.id_customer
INNER JOIN ps_order_history h ON o.id_order = h.id_order
INNER JOIN ps_order_state_lang s ON s.id_order_state = h.id_order_state
WHERE s.id_lang =6
GROUP BY c.id_customer
HAVING MAX(h.date_add)
For each customer, this query is selecting the first date (the field h.date_add) when I need of the last one. It seems the MySQL is ignoring the HAVING.
I tried to make a sub-select, but it doesn't work too.
Thanks any answer.
Here, you need to have a subquery which gets the latest date_add for every id_order on table ps_order_history. The result of the subquery is then joined back on the original table ps_order_history provided that it macth on two columns: date_add and id_order.
SELECT c.firstname,
c.lastname,
d.product_name,
o.payment,
s.name,
h.date_add
FROM ps_orders o
INNER JOIN ps_order_detail d ON d.id_order = o.id_order
INNER JOIN ps_customer c ON c.id_customer = o.id_customer
INNER JOIN ps_order_history h ON o.id_order = h.id_order
INNER JOIN
(
SELECT id_order, MAX(date_add) max_date
FROM ps_order_history
GROUP BY id_order
) x ON h.id_order = x.id_order AND
h.date_add = x.max_date
INNER JOIN ps_order_state_lang s ON s.id_order_state = h.id_order_state
WHERE s.id_lang =6
GROUP BY c.id_customer
To get the last date, you need to join it in:
SELECT c.firstname, c.lastname, d.product_name, o.payment, s.name, h.date_add
FROM ps_orders o
INNER JOIN ps_order_detail d ON d.id_order = o.id_order
INNER JOIN ps_customer c ON c.id_customer = o.id_customer
INNER JOIN ps_order_history h ON o.id_order = h.id_order
INNER JOIN ps_order_state_lang s ON s.id_order_state = h.id_order_state
inner join (select o.id_customer, max(oh.date_add) as maxdate from ps_order_history h join ps_order o on h.id_order = o.id_order group by o.id_customer) omax on omax.id_customer = o.id_customer and o.date_add = omax.maxdate
WHERE s.id_lang =6
GROUP BY c.id_customer
Your having clause calculates the maximum date and then succeeds when it is not equal to 0 (which would be most of the time).

Multiple inner joins to get a complex report, not working

For the schema below, I need to get this report
This is what I have
select c.name, sr.name, count(o.order_id)
from contact c
INNER JOIN accounts a
ON c.account_id=a.account_id
INNER JOIN sales_reps sr
ON a.sales_rep_id =sr.sales_rep_id
INNER JOIN orders o
ON a.account_id =o.account_id
where o.order_id in (
select SUM(oi.quantity*p.price) from
order_items oi INNER JOIN parts p
on oi.part_id =p.part_id
)
group by a.account_id, c.name
But this does not give any results.
Please help.
Your where condition is not right, how should be a order_id equal a sum?
Try the below:
select
c.name, sr.name, COUNT(o.order_id), SUM(op.order_total)
FROM
contact c
INNER JOIN
accounts a ON c.account_id = a.account_id
INNER JOIN
sales_reps sr ON a.sales_rep_id = sr.sales_rep_id
INNER JOIN
orders o ON a.account_id = o.account_id
INNER JOIN
(SELECT
oi.order_id, SUM(oi.quantity * p.price) AS order_total
FROM
order_items oi
INNER JOIN
parts p ON oi.part_id = p.part_id
GROUP BY
oi.order_id
) op ON o.order_id = op.order_id
WHERE o.delivery_data >= CURDATE()
GROUP by c.contact_id
It won't give results as your WHERE ... IN SELECT is based on a query returning a sum() value which will not equal a key (most likely), or incorrect at best... and since you are dealing with a quantity and price which will have decimal precision (typically), you won't even get that to match even LESS likely...
I would swap the query around to pre-qualify the orders within a given date in question and sum that... THEN join to rest...
select
c.name,
sr.name,
PreQualified.NumberOrders,
PreQualified.OrderTotal
from
( select
o.Account_ID,
count( distinct o.order_id ) as NumberOrders,
sum( oi.quantity * p.price ) as OrderTotal
from
orders o
join order_items oi
on o.order_id = oi.order_id
join parts p
on oi.part_id = p.part_id
where
o.Delivery_Date >= CURDATE()
group by
o.Account_ID ) as PreQualified
JOIN Accounts a
on PreQualified.Account_ID = a.Account_ID
Join Contact C
on a.Account_ID = c.Account_ID
JOIN Sales_Reps sr
ON a.sales_rep_id = sr.sales_rep_id
If you want to count records use
count(*)
Instead of
count(o.order_id)