selecting entries that are referenced in one of multiple tables - sql

I have four tables:
company
id | name
order
number | company_id
quote
number | company_id
invoice
number | company_id
I want to get the list of companies that are referenced in any of the three (i.e., exclude companies that aren't in any).
I wrote this query:
select c.id, c.name from company c
left outer join order o on o.company_id = c.id
left outer join quote q on q.company_id = c.id
left outer join invoice i on i.company_id = c.id
where o.number is not null or q.number is not null or i.number is not null
But the order, quote, and invoice tables are quite large. So the join causes the query to run forever (one join is O(m*n), three joins is O(m*n*p*q)).
I COULD run this query basically three times with only one join on each query (O(m*n) + O(m*p) + O(m*q)), but I'm hoping for a more optimal solution.
This is for Oracle

Join to a subquery which does a union of the three order tables:
SELECT
c.id, c.name
FROM company c
INNER JOIN
(
SELECT company_id FROM order
UNION
SELECT company_id FROM quote
UNION
SELECT company_id FROM invoice
) t
ON c1.id = t.company_id
The union queries should automatically remove duplicate company_id, such that only distinct companies which are present in any of the three tables should be in the result set of that subquery. The inner join then filters off any companies which were not present at all.

Related

SQL Join two tables only if they both contain all records

I have samples, sample_products, products, orders and order_products.
Samples <=> Products (through sample_products)
Order <=> Products (through order_products).
There is no connection between Order and Samples.
Now I need to find the most used Samples on an Order. This is particularly a problem because if we for example have a package of 2 products - product A and product B, an order needs to contain both of them, not only product A or not only product B.
An order has to contain only and exactly those 2 products to be considered a sample.
I tried joining them like this but this leads to the problem I mentioned before - it does not ensure the order does not contain other products or that both A and B are present.
SELECT * FROM samples
INNER JOIN sample_products ON sample_products.sample_id = samples.id
INNER JOIN products ON products.id = sample_products.product_id
INNER JOIN order_products ON order_products.product_id = products.id
INNER JOIN orders ON orders.id = order_products.order_id
How can I make sure that it only joins the table together if both product A and B are present?
If you want to count full sample set (if sample1 consits from A,B,C -> count oreder with A,B,C), you can use number of product for join:
SELECT order_sample_count.sample_id,
COUNT(order_sample_count.order_id) as sample_use
FROM
(
SELECT sample_id, count(product_id) as semple_numbers
FROM
(
SELECT DISTINCT sample_id, sample_products.product_id
FROM samples
INNER JOIN sample_products ON sample_products.sample_id = samples.id
) AS sample_distinct
GROUP BY sample_id
) AS semple_count
INNER JOIN
)
SELECT order_id, sample_id, count(product_id) as semple_numbers
FROM
(
SELECT DISTINCT order_products.order_id, sample_products.sample_id, order_products.product_id
FROM order_products
INNER JOIN sample_products ON sample_products.product_id = order_products.product_id
) AS order_sample_distinct
GROUP BY order_id, sample_id
) AS order_sample_count ON semple_count.sample_id = order_sample_count.sample_id
AND semple_count.semple_numbers = order_sample_count.semple_numbers
GROUP BY order_sample_count.sample_id

Left Join gives me a lot of duplicate value

I have two tables.there are 3 common columns. When I use left join it gives me a lot duplicate values. How should I avoid the duplicate.
You need to use left join as below:
For Example:
SELECT
cu.Id
,cu.CustomerName,
_ord.Total
FROM Customers cu
LEFT JOIN
(
SELECT
customerId
,sum(amount) Total
FROM Orders
GROUP BY customerId
) _ord on _ord.customerId=cu.id

SQL - joining multiple tables

I have three tables that I'm trying to join:
sales
order
employee
For example, the tables have the following attributes.
Sales:
ID
price
Order:
ID
tag
Employee:
tag
yearsWorked
I would like to keep only records that exist from the result of a left join in sales and order -> left join the result with employee
SELECT *
FROM ( SELECT *
FROM SALES
LEFT JOIN ORDER
ON SALES.ID = ORDER.ID) AS SO
LEFT JOIN EMPLOYEE
on SO.TAG = EMPLOEYE.TAG;
The above query does not work.
There is no need for a subquery. All you have to do is 2 LEFT JOIN, each for the respective table. This will make sure that only the results of the first left join are joined with the third table.
SELECT *
FROM SALES S
LEFT JOIN ORDER O ON S.ID = O.ID
LEFT JOIN EMPLOYEE E ON O.TAG = E.TAG;
I hope this works.
SELECT
*
FROM
Order
LEFT JOIN Sales
ON Order.ID = Sales.ID
LEFT JOIN Employee
ON Order.tag = Employee.tag

left join two tables on a non-unique column in right table

I have two tables in sql server and i wanna select and join some data from these table.the first tables have some customer like:
---------------
customer id
Dave 1
Tom 2
---------------
and second table i table of purchases that includes list of last purchases with cost and which customer bought that Product:
------------------
product date customer id
PC 1-1-2000 1
phone 2-3-2000 2
laptop 3-1-2000 1
------------------
i wanna select first table (customers info) with last date of their purchases!
i tried left join but that doesn't give me last purchases becuase customer id is not unique in second table! how can i do this function with SQL server query? Regards
If you just want the max date, use aggregation. I would recommend a left join for customers who have made no purchases:
select c.customer, c.id, max(p.date)
from customers c left join
purchases p
on c.id = p.customer_id
group by c.customer, c.id;
Use the not exists clause for the win!
select c.customer, p.*
from Customer as c
inner join Purchase as p
on p.customer_id = c.id
where not exists (
select 1
from Purchase as p2
where p2.customer_id = p.customer_id
and p2.date > p.date
)
I think you can use inner join and group by
select table1.customer, table1.id, table.max(date)
from table1
inner join table2 on table1.id = table2.id
group by table1.customer, table1.id

How to do a join with multiple conditions in the second joined table?

I have 2 tables. The first table is a list of customers.
The second table is a list of equipment that those customers own with another field with some data on that customer (customer issue). The problem is that for each customer, there may be multiple issues.
I need to do a join on these tables but only return results of customers having two of these issues.
The trouble is, if I do a join with OR, I get results including customers with only one of these issues.
If I do AND, I don't get any results because each row only includes one condition.
How can I do this in T-SQL 2008?
Unless I've misunderstood, I think you want something like this (if you're only interested in customers that have 2 specific issues):
SELECT c.*
FROM Customer c
INNER JOIN CustomerEquipment e1 ON c.CustomerId = e1.CustomerId AND e1.Issue = 'Issue 1'
INNER JOIN CustomerEquipment e2 ON c.CustomerId = e2.CustomerId AND e2.Issue = 'Issue 2'
Or, to find any customers that have multiple issues regardless of type:
;WITH Issues AS
(
SELECT CustomerId, COUNT(*)
FROM CustomerEquipment
GROUP BY CustomerId
HAVING COUNT(*) > 1
)
SELECT c.*
FROM Customer c
JOIN Issues i ON c.CustomerId = i.CustomerId
SELECT *
FROM customers as c
LEFT JOIN equipment as e
ON c.customer_id = e.customer_id --> what you are joining on
WHERE (
SELECT COUNT(*)
FROM equipment as e2
WHERE e2.customer.id = c.customer_id
) > 1
You can do it with a sub query instead of Joins:
select * from Customer C where (select Count(*) from Issue I where I.CustomerID = C.CustomerID) < 2
or whatever value you want