-1

I am new to sql and practising from w3schools. https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_join_left

In venn diagram,it has shown the different types of Join.But,I am trying to get this part of venn diagram.

enter image description here

So,I tried this way using subquery.:

SELECT Customers.CustomerName, Orders.OrderID
FROM Customers
LEFT JOIN Orders
WHERE CUSTOMERS.CUSTOMERID NOT IN (SELECT CUSTOMERID FROM ORDERS);

But,is it possible to get only the left part of the venn diagram(Not the intersecting data) without using subqueries and not using "In" statements?If,it is possible then,please share me the solution.

Ashwin Karki
  • 249
  • 4
  • 18
  • how about not exists? or you can use "select * from (select t1..leftjoin...) where t2.col = null) – Ed Bangga Sep 12 '19 at 03:44
  • We don't know how to read the Venn diagram, you don't give a legend. It makes no sense; none of result rows even have the same columns as the input rows. Anyway tables aren't sets of rows, they are bags of rows. You are parroting something you have seen without actually understanding it & are not communicating anything by it. In special circumstances it can describe SQL EXCEPT; but you haven't given those. [Venn diagrams are generally inappropriate for SQL.](https://stackoverflow.com/a/55642928/3404097) PS That web site is a poor resource. And they don't explain the diagram either. – philipxy Aug 19 '22 at 08:38
  • When giving a business relation(ship)/association or table (base or query result), say what a row in it states about the business situation in terms of its column values. – philipxy Aug 19 '22 at 08:44

5 Answers5

2

All those records from customers that have no orders:

SELECT *
FROM Customers c
LEFT JOIN Orders o ON o.CustomerId = c.CustomerId
WHERE o.CustomerId IS NULL 

Not really sure I would represent your customers orders relationship like that vent diagram because it implies to me that there can be orders that have no customers but I'll overlook that

When we left join we get all the customers plus any orders they have made. Customers that have made no orders have a null in the related o.CustomerId and that is what we look for in the where clause

It is most reliable to use (one of) the column(s) specified in the join condition when doing this test. Any other column from orders might be null for other reasons (product type not known, for example) unless it is specified as NOT NULL in the table definition. To save looking this up we rely on the fact that the only way o.CustomerId can be null in this particular query (where it is mentioned in the join) is if there is no matching order row for that customer

You could also use either these:

SELECT *
FROM Customers c
WHERE c.CustomerId NOT IN (SELECT CustomerId FROM orders)

SELECT *
FROM Customers c
WHERE NOT EXISTS (SELECT null FROM orders o WHERE o.CustomerID = c.CustomerID)

In most high end database systems these will all be implemented the same under the hood; the query compiler will recognise the job they're trying to do and carry them out in the same way. There's a risk that the NOT IN will perform poorly in some databases, particularly older or more naively written ones, and it's perhaps a reasonable rule of thumb to follow that "do not use IN for lists longer than you would happily type in manually". The EXISTS version is called a coordinated subquery and is often a fairly succinct and high performing way of doing things like this- for a long time databases have had specific optimisations for EXISTS that they formerly might not have had for a JOIN based route but that's again something that has largely gone away nowadays. Seeing someone exhibit a preference for EXISTS may indicate they've been using SQL a loooong time, as it was frequently the best performing way of answering this type of query in ancient databases

Of all 3 I find the join method clearest to read and understand - coordinated subqueries always require a bit more mental effort to see how they hook into the bigger picture because they refer to columns that aren't part of their local scope. It's also possible to make a mistake with a coordinated subquery more easily than the other forms, and particularly with the IN, by typoing a column from the outer query into the inner query, changing the results it emits.

Use whatever works for you; being able to read and understand all these forms will help you when you read other people's code

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • oh thank you but your result is returning 17 records whereas my query returned me 3000 record.is there any problem in my subquery? – Ashwin Karki Sep 12 '19 at 03:47
  • Technically your query returns no rows because it has a syntax error (missing ON clause) unless you're using some database system that permits this (in which case it's filling in some join condition for you or performing a cross join, and you're getting 3000 records because every row from customers is combined with every row from orders). I cannot speculate further on what I cannot see, but I've been doing sql a long time; trust me- this way of using left join to find all customers that have no orders, is correct. Feel free to manually check your 17 to prove it – Caius Jard Sep 12 '19 at 03:53
1

Below query will only select Customers that don't have Orders as per requirements.

SELECT c.CustomerName, o.OrderID
FROM Customers c
LEFT JOIN Orders o on o.CUSTOMERID = c.CUSTOMERID
WHERE o.OrderID IS NULL

Customer  Orders
1         1
2         null
3         2

should only give

Customer   Orders
2          null
Ed Bangga
  • 12,879
  • 4
  • 16
  • 30
  • why did you put t1.OrderID IS NULL – Ashwin Karki Sep 12 '19 at 03:51
  • My question is why wrap it in a needless outer select? – Caius Jard Sep 12 '19 at 03:51
  • you required to display Customer info that don't have orders based on your venn diagram – Ed Bangga Sep 12 '19 at 03:51
  • This is exactly same as @Caius Jard so please accept that answer as he answered first. Please delete this answer to obey some rules. – Shushil Bohara Sep 12 '19 at 04:01
  • @Susang, why is it the same? Calius is using customerid is null. – Ed Bangga Sep 12 '19 at 04:13
  • Good question, but you should know that, `CUSTOMERID` is `NULL` means whole row is null in the table. Even if you use the other column than `OrderID` it will return the same result. Just give it try :) – Shushil Bohara Sep 12 '19 at 04:19
  • its not possible for orders to have null customerid – Ed Bangga Sep 12 '19 at 04:24
  • @metal you're splitting hairs there by saying "he uses x and i use y" and you know it; you should also know your query might actually be wrong in some cases, such as the possibility that orderid can be null for other reasons than if the join failed (what if an order doesn't have an ID while it is a draft order the customer hasn't placed?) - the only reliable way without having to look up whether the column is NOT NULL (which we can't do as the table def isn't shown to us) is to use a column from the join. You're teaching people here, and sadly this answer sends a couple of incorrect messages – Caius Jard Sep 12 '19 at 04:25
0

If you are looking for customers who have not ordered, their order id will be null anyway (this is what your Venn diagram says):

SELECT Customers.CustomerName
FROM Customers
WHERE CUSTOMERS.CUSTOMERID NOT IN (SELECT CUSTOMERID FROM ORDERS);
Neeraj Agarwal
  • 1,059
  • 6
  • 5
0

You need to use EXCEPT clause. Also you need to define which tables to join.

SELECT Customers.CustomerName, Orders.OrderID
FROM Customers
LEFT JOIN Orders on Orders.CustomerID=Customers.CustomerID

EXCEPT

SELECT Customers.CustomerName, Orders.OrderID
FROM Customers
LEFT JOIN Orders on Orders.CustomerID=Customers.CostomerID
WHERE CUSTOMERS.CUSTOMERID NOT IN (SELECT CUSTOMERID FROM ORDERS);    
0

If a Customer is not having Orders, you will not have OrderID. You can check like below:

SELECT Customers.CustomerName, NULL AS OrderID
FROM Customers AS C
WHERE NOT EXISTS (
SELECT CUSTOMERID FROM ORDERS AS O WHERE O.CustomerID = C.CustomerID);

You can also use SET operator MINUS(ORACLE), EXCEPT(SQL Server) to perform this

SELECT CustomerID, NULL AS OrderID
FROM
(SELECT CustomerID FROM Customers 
MINUS
SELECT CustomerID FROM Orders)
Venkataraman R
  • 12,181
  • 2
  • 31
  • 58