Using OR, AND operator in single query - php

I am trying to list the records which meets my condition. As ii am using AND and OR operator together i am not getting the exact report. Here is my query
SELECT o.sales_order_id AS SID, o.reference, o.status, o.last_modified, sol.sales_order_id, sol.item, sol.quantity, sol.selling_price, sol.discount, sol.tax, SUM(sol.tax_amount) AS Tamt, SUM(sol.total) as Total, i.iid, GROUP_CONCAT(DISTINCT i.name) AS iname, l.company, t.tax_id, t.name as tname, t.rate from orders o INNER JOIN before_order_line_items sol ON o.sales_order_id = sol.sales_order_id INNER JOIN leads l ON o.company_id=l.id INNER JOIN items i ON sol.item=i.iid INNER JOIN taxes t ON sol.tax=t.tax_id WHERE o.order_quote='Order' AND o.authorise='Yes' OR o.assigned_to=6 OR o.user_id=6 GROUP BY o.sales_order_id ORDER BY o.sales_order_id DESC
I am storing both orders and quotations in single table Orders, for orders i store it as Order in order_quote column, for Quotations it is Quote
It is not checking order_quote='Order' condition, it displays both orders and quotations.
if i remove OR o.assigned_to=6 OR o.user_id=6 , it gives proper result.
I tried using DISTINCT like this
SELECT DISTINCT o.order_quote=`Order`, .....
But does't work.
UPDATED
SELECT o.sales_order_id AS SID, o.reference, o.status, o.last_modified, sol.sales_order_id, sol.item, sol.quantity, sol.selling_price, sol.discount, sol.tax, SUM(sol.tax_amount) AS Tamt, SUM(sol.total) as Total, i.iid, GROUP_CONCAT(DISTINCT i.name) AS iname, l.company, t.tax_id, t.name as tname, t.rate from orders o INNER JOIN before_order_line_items sol ON o.sales_order_id = sol.sales_order_id INNER JOIN leads l ON o.company_id=l.id INNER JOIN items i ON sol.item=i.iid INNER JOIN taxes t ON sol.tax=t.tax_id WHERE (o.order_quote='Order' AND o.authorise='Yes') AND (o.assigned_to=6 OR o.user_id=6) GROUP BY o.sales_order_id ORDER BY o.sales_order_id DESC

You need to use parentheses. I'm not sure exactly how, but your current where clause is interpreted as:
WHERE (o.order_quote = 'Order' AND o.authorise = 'Yes') OR
(o.assigned_to = 6) OR
(o.user_id = 6)
I would guess that you want something like this:
WHERE (o.order_quote = 'Order' AND o.authorise = 'Yes') AND
(o.assigned_to = 6 OR o.user_id = 6)
But that is mere speculation.
Or perhaps:
WHERE (o.order_quote = 'Order' AND
(o.authorise = 'Yes' OR o.assigned_to = 6 OR o.user_id = 6)

Related

Need distinct value based on id when we JOIN 4 tables in PHP/MYSQL

Here is my SQL query which joins 4 tables and it works correctly.
SELECT pl.lms_id, u.id, REPLACE(trim(u.`url`), 'www.', '') AS url, trim(u.`name`) as name, p.date_removed, p.status, p.ignore_status FROM `adl_seo_status` p INNER JOIN `adl_user_profiles` u on p.profile_id = u.id INNER JOIN adl_tw_profile_acc_type ac on p.profile_id = ac.profile_id LEFT JOIN `adl_lms_prof_list` pl on u.id = pl.profile_id WHERE u.`vpg_id`='2' AND u.`status` = 'Y' and ac.acc_type_id = '2' ORDER BY u.`url` ASC, p.id DESC
I am facing an issue that, the table adl_seo_status has multiple entries for a single profile_id. So, that accounts are repeating in my listing. I want that account as a single row which means the distinct value of accounts based on profile_id.
You need to use group by, for example:
SELECT
pl.lms_id,
u.id,
REPLACE(trim(u.`url`), 'www.', '') AS url,
trim(u.`name`) AS name,
p.date_removed,
p.status,
p.ignore_status
FROM `adl_seo_status` p INNER JOIN `adl_user_profiles` u ON p.profile_id = u.id
INNER JOIN adl_tw_profile_acc_type ac ON p.profile_id = ac.profile_id
LEFT JOIN `adl_lms_prof_list` pl ON u.id = pl.profile_id
WHERE u.`vpg_id` = '2' AND u.`status` = 'Y' AND ac.acc_type_id = '2'
ORDER BY u.`url` ASC, p.id DESC GROUP BY p.profile_id;

Mysql left join issue with 3 tables not returning all rows from first table

I have below query
select catid, cat_name, currency, count(is_reporting_category_sales.id) as total_sales,
sum(total_sales) as total_earning
from is_category
left join is_reporting_category_sales on is_category.catid = is_reporting_category_sales.category_id
join is_reporting_order on is_reporting_order.id = is_reporting_category_sales.order_id
group by catid, cat_name, currency
ORDER BY `is_category`.`cat_name` ASC
but this is returning only rows that are common in is_category and is_reporting_category_sales, is_reporting_order but I want to fetch all rows from is_category table. And if there is no order for the category then 0 as total_earning and total_sales.
You have to Use Left Join
left join is_reporting_order on is_reporting_order.id = is_reporting_category_sales.order_id
Instead of
join is_reporting_order on is_reporting_order.id = is_reporting_category_sales.order_id
Perhaps using left outer joins you might get the results you expect ( had to guess at some of the aliases for columns btw so some of them might be wrong )
select c.`catid`, c.`cat_name`, `currency`, count(i.`id`) as 'total_sales', sum(`total_sales`) as 'total_earning'
from `is_category` c
left outer join `is_reporting_category_sales` i on c.`catid` = i.`category_id`
left outer join `is_reporting_order` on o.`id` = i.`order_id`
group by c.`catid`, c.`cat_name`, `currency`
order by c.`cat_name` asc;

Combine two MySql into one query

I have two sql queries that I need to combine into one query for better efficiency, just not sure how to do it. Basically I need to query my Supplier, then for each supplier check to see if the Listing table has more than one record that matches based upon "supplier id", if it does then I need to return the supplier name and id. Here are my two queries:
Query 1:
SELECT s.name, s.id
FROM Supplier s
Query 2:
SELECT l.asin,
l.id,
COUNT(*) c
FROM Listing l
LEFT JOIN Product p
ON p.id = l.product_id
LEFT JOIN Supplier s
ON p.supplier_id = s.id
WHERE (l.matchValidated IS NULL OR l.matchValidated = 0)
AND s.id = SUPPLIER_ID_GOES_HERE
GROUP BY l.asin HAVING c > 1);
You already have supplier joined in the second query so you just need to add the supplier name and id to your SELECT and GROUP BY.
SELECT l.asin,
l.id,
s.name AS supplier_name,
s.id AS supplier_id,
COUNT(*) c
FROM Listing l
LEFT JOIN Product p
ON p.id = l.product_id
LEFT JOIN Supplier s
ON p.supplier_id = s.id
WHERE (l.matchValidated IS NULL OR l.matchValidated = 0)
GROUP BY l.asin, l.id, s.name, s.id
HAVING c > 1;

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.

How to write JOIN QUERY for 4 tables in the below condition

I have 4 tables ACCOUNTS_TABLE , LINKS_TABLE, GROUPS_TABLE, KEYS_TABLE
I need to get all accounts details which is of acct_type xx with count of Links, groups& keywords . I have tried this query but it gives all count as 0
SELECT
acc.acct_id, acc.acct_type, count(link.id) as link_count, link.account,
groups.camp_id, count(groups.id) as group_count, count(keyword.key_id) as key_count
FROM ".ACCOUNTS_TABLE." as acc
LEFT JOIN ".LINKS_TABLE." as link ON link.account=acc.acct_id AND acct_type='xx'
LEFT JOIN ".GROUPS_TABLE." as groups ON groups.camp_id=link.id
LEFT JOIN ".KEYS_TABLE." as keyword ON keyword.camp_id=link.id
GROUP BY acc.acct_id
My required output should be like this
Any one please help me to slove this problem
You probably should use COUNT(DISTINCT ....).
SELECT acc.acct_id, COUNT(DISTINCT link.id), COUNT(DISTINCT groups.id), COUNT(DISTINCT keyword.key_id)
FROM ACCOUNTS_TABLE acc
LEFT OUTER JOIN LINKS_TABLE link ON link.account = acc.acct_id AND acct_type = 'advertiser'
LEFT OUTER JOIN GROUPS_TABLE groups ON groups.camp_id = link.id
LEFT JOIN KEYS_TABLE keyword ON keyword.id = link.id
WHERE acc.acct_type = 'xx'
GROUP BY acc.acct_id
EDIT
Amended to use the updated join conditions, etc:-
SELECT acc.acct_id, acc.acct_type, COUNT( DISTINCT link.id ) , COUNT( DISTINCT groups.id ) , COUNT( DISTINCT keyword.key_id )
FROM ACCOUNTS_TABLE acc
LEFT OUTER JOIN LINKS_TABLE link ON link.account = acc.acct_id
LEFT OUTER JOIN GROUPS_TABLE groups ON groups.camp_id = link.id
LEFT JOIN KEYS_TABLE keyword ON keyword.camp_id=link.id
WHERE acc.acct_type = 'xx'
GROUP BY acc.acct_id, acc.acct_type
You could try something like this:
SELECT ACC.Id
,( SELECT COUNT (*) FROM Links L WHERE L.AccountId = ACC.Id ) AS CountOfLinks
,( SELECT COUNT (*) FROM Groups G WHERE G.AccountId = ACC.Id ) AS CountOfGroups
FROM ( SELECT Id FROM Accounts Acc WHERE Acc.Type = 'some type' ) ACC
I've rejigged your code a bit (see below) for a few reasons:
It's helpful (for me anyway) to write my SELECT statements always in a certain way - with anything that is not being grouped placed first, and ideally putting things in same order as my JOINs and doing the same in my GROUP BY
I put anything which restricts my FROM table into the WHERE not the JOIN to make it clearer what I'm trying to do and also to make it easier to modify later on.
I also like to ensure it's well laid out to make it easier to scan for issues.
Take this rearranged query and read through it to make sure you are getting the behaviour you're expecting.
PS I'm not sure about your table names and quotation style - I usually use back ticks (`) and would never put dots (.) in my table names. If you put these in as placeholders that's fine but they could lead to trouble for you if they are real.
SELECT
acc.acct_id,
-- if you don't group by these then you need to remove them as they will just return the first values based on mysql behaviour
acc.acct_type,
link.account,
groups.camp_id,
-- these counts will only count where an ID is present which seems like what you're after
count(link.id) as link_count,
count(groups.id) as group_count,
count(keyword.key_id) as key_count
FROM ".ACCOUNTS_TABLE." as acc
LEFT JOIN ".LINKS_TABLE." as link ON link.account=acc.acct_id
LEFT JOIN ".GROUPS_TABLE." as groups ON groups.camp_id=link.id
LEFT JOIN ".KEYS_TABLE." as keyword ON keyword.id=link.id
WHERE acct_type='advertiser'
GROUP BY acc.acct_id,
-- only use these if you intend to group by them
acc.acct_type,
link.account,
groups.camp_id DESC
SELECT acct_type,
count(acct_type),
count(l.id),
count(g.id),
count(key_id)
FROM accounts a
LEFT JOIN links l ON (l.account = a.acct_id)
LEFT JOIN groups g ON (g.camp_id = l.id)
LEFT JOIN keysTable k ON k.group_id = g.id
GROUP BY acct_type HAVING acct_type = 'xx';
SQL Fiddle Validated: http://www.sqlfiddle.com/#!2/f4b6a/20
SELECT
accounts_table.acct_id,
accounts_table.acct_type,
COUNT(DISTINCT links_table.id) AS link_count,
COUNT(DISTINCT groups_table.id) AS group_count,
COUNT(DISTINCT keys_table.key_id) AS key_count
FROM
accounts_table
LEFT JOIN
links_table
ON links_table.account = accounts_table.acct_id
LEFT JOIN
groups_table
ON groups_table.camp_id = links_table.id
LEFT JOIN
keys_table
ON keys_table.camp_id = links_table.id
WHERE
acct_type = 'xx'
GROUP BY
accounts_table.acct_id,
accounts_table.acct_type
ORDER BY
link_count DESC,
group_count DESC,
key_count DESC
Edited answer to match updated question - this should do what you've asked for.
This should do what you've asked for, SQL fiddle here - http://www.sqlfiddle.com/#!2/f4b6a/20

Categories