Performing a join on ZenCart's address book entries - php

I have the following bits of code:
$referrers_query =
select c.customers_id, c.customers_firstname, c.customers_lastname,
c.customers_email_address, c.customers_telephone, a.entry_street_address,
a.entry_city, a.entry_state, a.entry_country_id, n.countries_name,
a.entry_zone_id, a.entry_postcode, r.referrer_customers_id,
r.referrer_key, r.referrer_homepage, r.referrer_approved,
r.referrer_banned, r.referrer_commission from customers as c,
address_book as a, referrers as r, countries as n
where a.entry_country_id = n.countries_id and c.customers_id = r.referrer_customers_id
and a.address_book_id = c.customers_default_address_id order by c.customers_lastname;
What I would like to do, is instead of making a WHERE clause join, I'd like to nest the joins.
There are five database tables noted above.
customers, address_book, referrers, countries, zones.
But I have no idea where to get started. The main problem with this is using the above statement, I seem to lose a few records from the select. This is because some records are using a 'zone_id' = 0. A fix to this was to simply create a blank record for 0 but besides that, can I use a join to fix this?

The query written with explicit JOINs:
SELECT c.customers_id, c.customers_firstname, c.customers_lastname,
c.customers_email_address, c.customers_telephone, a.entry_street_address,
a.entry_city, a.entry_state, a.entry_country_id, n.countries_name,
a.entry_zone_id, a.entry_postcode, r.referrer_customers_id,
r.referrer_key, r.referrer_homepage, r.referrer_approved,
r.referrer_banned, r.referrer_commission
FROM customers AS c
JOIN referrers AS r ON (c.customers_id = r.referrer_customers_id)
JOIN address_book AS a ON (a.address_book_id = c.customers_default_address_id)
JOIN countries AS n ON (a.entry_country_id = n.countries_id)
ORDER BY c.customers_lastname
If you want to also get the info from the zones table if a match exists, you would need to add a LEFT JOIN like this:
SELECT c.customers_id, c.customers_firstname, c.customers_lastname,
c.customers_email_address, c.customers_telephone, a.entry_street_address,
a.entry_city, a.entry_state, a.entry_country_id, n.countries_name,
a.entry_zone_id, a.entry_postcode, r.referrer_customers_id,
r.referrer_key, r.referrer_homepage, r.referrer_approved,
r.referrer_banned, r.referrer_commission
FROM customers AS c
JOIN referrers AS r ON (c.customers_id = r.referrer_customers_id)
JOIN address_book AS a ON (a.address_book_id = c.customers_default_address_id)
JOIN countries AS n ON (a.entry_country_id = n.countries_id)
LEFT JOIN {zones table name} AS z ON (z.{zones id column name} = a.entry_zone_id)
ORDER BY c.customers_lastname
and also add the columns you want to select to the top of the query. A LEFT JOIN always returns a result from the left table (first one listed) and if there is no match in the right table, it returns NULLs for the right table's columns.

Related

Left Join - Select ALL from left table but select only the latest from right table

I have 2 tables, borrowers and loans. I want to display on the main page the list of ALL borrowers with or without loans. If with loan, display the newest one.
I have the following sql query, basically it returns the above description except it displays the very first loan of the borrower instead of the latest one.
(Side note: I used GROUP BY to avoid duplicates. Without it the query returns duplicated borrower names if they have multiple loans. Just wanted to know if this is an efficient way of doing so.)
SELECT b.b_id,
b.isdeleted,
b.picture,
b.firstname,
b.middlename,
b.lastname,
b.address,
b.contactno,
b.birthday,
b.businessname,
b.occupation,
b.comaker,
b.comakerno,
b.remarks,
b.datecreated,
b.activeloan,
l.l_id,
l.amount,
l.payable,
l.balance,
l.mode,
l.term,
l.interestrate,
l.amortization,
l.releasedate,
l.duedate,
l.status,
l.c_id
FROM borrowers as b
LEFT JOIN loans as l ON b.b_id = l.b_id
WHERE b.isdeleted = 0
GROUP BY b.b_id
It seems the below query does exactly what i wanted.
I added the below subquery on the "ON" clause.
(SELECT MAX(l_id)
FROM jai_db.loans as l2
WHERE l2.b_id = b.b_id LIMIT 1)
SELECT b.b_id, b.isdeleted, b.picture, b.firstname, b.middlename, b.lastname, b.address, b.contactno,
b.birthday, b.businessname, b.occupation, b.comaker, b.comakerno, b.remarks, b.datecreated, b.activeloan,
l.l_id, l.amount, l.payable, l.balance, l.mode, l.term, l.interestrate, l.amortization,
l.releasedate, l.duedate, l.status, l.c_id
FROM jai_db.borrowers as b
LEFT JOIN jai_db.loans as l
ON l.l_id = (SELECT MAX(l_id)
FROM jai_db.loans as l2
WHERE l2.b_id = b.b_id LIMIT 1)
WHERE b.isdeleted = 0

Mysql query can not retrieve data as per condition

I have one issue. I need to retrieve data from database as per some condition but some cases it fails. I am explaining my query below.
select b.member_id as b_member_id,
b.rest_name,
b.city,
b.proviance,
b.postal,
b.address,
b.country,
b.person,
b.mobile,
b.url,
b.status,
b.premium,
b.image,
b.business_phone_no,
b.email,
b.multiple_image,
b.latitude,
b.longitude,
b.quadrant,
d.member_id as d_member_id,
d.day_id,
d.cat_id,
d.subcat_id,
d.comment,
d.city,
d.special_images,
c.cat_id,
c.special,
sub.subcat_id,
sub.subcat_name,
sub.status,
sl.day_id,
sl.member_id,
sl.date_from,
sl.date_to
from db_restaurant_basic as b left join db_restaurant_detail as d on b.member_id=d.member_id
left join db_category as c on d.cat_id=c.cat_id
left join db_subcategory as sub on d.subcat_id=sub.subcat_id
left join db_special_images as sl on d.day_id=sl.day_id
where b.city='2' and d.day_id='4' and c.special='1'
and (((sl.date_from IS NULL or sl.date_from='') and (sl.date_to IS NULL or sl.date_to='')) or( sl.date_from <='2016-10-27' and sl.date_to >= '2016-10-27' ))
and b.status=1
and sub.status=1 group by d.subcat_id ORDER BY b_member_id DESC
Here my problem is some value also is coming which does not match the condition. Here b.city='2' but some value is coming which city=0 only also. Here i need the value should come as per proper matching. Please help me.
You are selecting d.city - from the db_restaurant_basic table - but the condition you set is b.city='2' - on the db_restaurant_detail table.
So any results with a city of 0, will show the city from the d / db_restaurant_detail table.
If you need to filter on that as well, you need to add and d.city=2.
You should probably check if you can normalize your database structure more to avoid having the same data in different tables.
Using the answer window's formatting options...
WHERE b.city = 2
AND d.day_id = 4 -- NOTE THAT THIS IS AN INNER JOIN!
AND c.special = 1 -- AND SO IS THIS !!
Since you have city twice in the selection list (b.city and d.city) I have to assume the city='0' value you mention is really d.city='0'. To make sure that also d.city is '2' you can add an additional condition in the where clause or you specify the join like this
select ... from db_restaurant_basic as b left join db_restaurant_detail as d on d.member_id=d.member_id and b.city = d.city left join ...
or even like this, getting rid of the ambiguity
select ... from db_restaurant_basic as b left join db_restaurant_detail as d using(member_id, city) left join ...

Using Joins To Retrieve Data Twice

I have the following two MySQL queries.
$delivery_id =
select c.countries_id
from orders o
LEFT JOIN countries c
ON c.countries_name = o.delivery_country
where o.orders_id = 1208;
$billing_id =
select c.countries_id
from orders o
LEFT JOIN countries c
ON c.countries_name = o.billing_country
where o.orders_id = 1208;
With the results being put into the variables (PHP) as appropriate. What I would like to know is, is there a way to combine these two queries into one singular query instead of running it twice. (This is using ZenCart's Query Factory ($db->Execute) where the results will be put into a fields array and recalled as such.
Info about the tables: Each order in orders will contain a billing and delivery address with a country name being found in the appropriate field (billing_country and delivery_country). However, not all orders will contain a delivery address. How can I combine these two into one query? I know that I can use a LEFT JOIN of some sort but am not sure on how to write it.
You can join the countries table two times using different alias names:
select
c1.countries_id AS delivering_id,
c2.countries_id AS billing_id
from orders o
LEFT JOIN countries c1
ON c1.countries_name = o.delivery_country
LEFT JOIN countries c2
ON c2.countries_name = o.billing_country
where o.orders_id = 1208;
Use union operator as ,
select c.countries_id
from orders o
LEFT JOIN countries c
ON c.countries_name = o.delivery_country
where o.orders_id = 1208
UNION
select c.countries_id
from orders o
LEFT JOIN countries c
ON c.countries_name = o.billing_country
where o.orders_id = 1208;

nested queries and calculations all in the same query - is it possible?

I am running a MySQL query to get all "users" with current orders.
(It is possible for a user to have more than 1 associated orders in the db/query).
However i also want to get the total order value for each user and total order count for each user that is being returned (within the below query).
I could do these calculations in PHP, but feel it is possible and would be neater all done within the same SQL query (if possible).
This is the basic query with no attempt to make the above calculations
SELECT u.UserID, u.UserName,
o.OrdersID, o.OrderProductName, o.OrderProductQT, o.OrderTotalPrice, o.tUsers_UserID, o.tOrderStatus_StatusID, o.OrderDate, o.OrderDateModified, o.OrderVoid, o.tProducts_ProductID,
os.OrderStatusName,
ud.UserDetailsName, ud.UserDetailsPostCode,
p.ProductName, p.ProductImage1
FROM tusers u
INNER JOIN torders o ON o.tUsers_UserID = u.UserID
INNER JOIN torderstatus os ON os.OrderStatus_StatusID = o.tOrderStatus_StatusID
INNER JOIN tuserdetails ud ON ud.tUsers_UserID = u.UserID
LEFT JOIN tproducts p ON p.ProductID = o.tProducts_ProductID
WHERE o.tOrderStatus_StatusID = ?
GROUP BY u.UserID
ORDER BY OrdersID DESC
I have tried various nested select queries, but none of them work (right)
Is what i want to do possible in SQL or should i just do it all in PHP once i have the returned query results?
Any advice is much appreciated
You can embed the slightly modified queries into another query. For instance:
SELECT userid, SUM(orderid) FROM orders GROUP BY userid
and
SELECT userid, SUM(distinct productid)
FROM
orders o
INNER JOIN orderlines ol on ol.orderid = o.orderid
GROUP BY
userid
can be combined to:
SELECT
u.userid
u.fullname,
(SELECT SUM(orderid)
FROM orders o
WHERE o.userid = u.userid) as ORDERCOUNT,
(SELECT SUM(distinct productid)
FROM
orders o
INNER JOIN orderlines ol on ol.orderid = o.orderid
WHERE
o.userid = u.userid) as UNIQUEPRODUCTS
FROM
users u
Note that the latter query will return all users and will return NULL for ORDERCOUNT or UNIQUEPRODUCTS when the subquery doesn't return anything (when a user doesn't have orders). Also, the query will fail when a subquery returns more than 1 row, which should never happen in the example I posted.

mysql query dont gets all posts

I have a MYSQL query who have to list all post i want it to post. But it dont do it. It shows posts when i have more then one post in the table "meaOrder" with the same "ordCode". But when i have only on post in meaOrder, i don't show it. What can i do?
SELECT koden, wish, rnamn, bild, pris, cname, onsktext
FROM (
SELECT m.wishText as onsktext, m.meaOID as midn, m.ordcode as koden, w.wish as wish, r.meaName as rnamn, r.meaImg as bild,
r.meaPrice as pris, k.catName as cname from cats k, meals r, wishes w,
meaOrder m
join orders c on c.ordNR=4401
WHERE c.ordStatus=1 AND m.ordNR=c.ordNR AND m.meaID=r.meaID AND m.wishesID=w.id
AND r.catID=k.catID
) T
GROUP BY koden, rnamn, bild, pris, cname
ORDER BY midn DESC
TABLE orders
http://grab.by/m74E
TABLE meaOrder http://grab.by/m74Q
Try replacing the JOIN with RIGHT JOIN in this case. The difference is explained at JOIN Syntax page in MySQL docs . In short - JOIN returns row only if there are corresponding rows in both joined tables (inner join). LEFT JOIN / RIGHT JOIN return all rows from one of the tables and corresponding row if it exists from the other table (those are outer joins)
Do you need a subselect?
This seems to cover it:-
SELECT m.ordcode AS koden, w.wish AS wish, r.meaName AS rnamn, r.meaImg AS bild, r.meaPrice AS pris, k.catName AS cname, m.wishText AS onsktext
FROM cats k
INNER JOIN meals r ON r.catID = k.catID
INNER JOIN meaOrder m ON m.meaID = r.meaID
INNER JOIN wishes w ON m.wishesID = w.id
INNER JOIN orders c ON m.ordNR = c.ordNR
WHERE c.ordStatus = 1
AND c.ordNR = 4401
GROUP BY m.ordcode, r.meaName, r.meaImg, r.meaPrice, k.catName
ORDER BY midn DESC

Categories