I have the following 2 SQL SELECT statements and am not able to wrap my head around how they're different:
SELECT DISTINCT product.maker
FROM product, pc
WHERE pc.model = product.model AND
product.maker NOT IN
(SELECT DISTINCT product.maker
FROM product, laptop
WHERE product.model = laptop.model)
and
SELECT DISTINCT p.maker
FROM Product p INNER JOIN
PC ON p.model = PC.model
WHERE p.maker NOT IN (SELECT ip.maker
FROM Laptop il INNER JOIN
Product ip ON il.model = ip.model
);
EDIT: The database schema is here - http://www.sql-ex.ru/help/select13.php#db_1
So first obvious difference is absence of DISTINCT in second query's subquery.
The other difference that the second one uses the keyword inner join.
Now, the first way of writing the query is the classical way when join keyword was non-existent.
Using join keyword helps when you have multiple types of join to do such as left join, etc.
Usually the query processor will generate the same database operations, so the performance would be same.
Related
I have two mySQL statements. First is:
SELECT o.OrderID, c.CustomerName, o.OrderDate
FROM Customers AS c, Orders AS o
WHERE c.CustomerID=o.CustomerID;
The second is:
SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate
FROM Orders
INNER JOIN Customers
ON Orders.CustomerID=Customers.CustomerID;
Both produce the same result, but second doesn't contain reference on Customers table in FROM request.
My question is - what is the difference between these two sql statements? In which cases should I use JOIN and in which cases should I use simple SELECT from two tables?
They are the same except the second is easier to read, so you should use that one.
Those JOIN are different, although the result are the same.
The First one is CROSS JOIN and adds the condition in where, which is implicit CROSS JOIN
The second one is INNER JOIN
If you want to connect two tables I would use INNER JOIN instead of CROSS JOIN Because the intention of the inner join table is clearer
Im supposed to be converting this query from MYSQL to SQL Server. However, the join statement is throwing me off. I haven't seen joins done like this and I am slightly confused on how to translate it.
SELECT
`Supplier Confirmed Orders` + `Log Tech Confirmed Orders` AS 'orders confirmed',
`Orders in CVN`-`Cancelled Orders` AS 'Orders in CVN',
tblloadingmonths.`month`,
tblvendorindex.`vendorindexid`,
'Service' AS category
FROM
tblloadingmonths
JOIN
tblvendorindex
LEFT JOIN
tblcvn ON tblloadingmonths.`month` = tblcvn.`month`
AND tblvendorindex.vendorindexid = tblcvn.vendorindexid
Whats throwing me off is that the loadingmonths and vendorindex tables dont have any common fields, but theyre being joined, and then left joined with cvn. I've always been taught to do tableA join tableB ON colA = colB join tableC ON colB = colC, but not tableA join talbeB left join tableC ON colA = colC AND colB = colC. As it stands, the query cant run in SQL Server with the joins the way the way they are. I had to set it up like this:
SELECT
CVN.[Supplier Confirmed Orders] + CVN.[Log Tech Confirmed Orders] AS 'orders confirmed',
(CVN.[Orders in CVN] - CVN.[Cancelled Orders]) AS 'Orders in CVN',
tblloadingmonths.month,
tblvendorindex.vendorindexid,
'Service' AS category,
'CVN Compliance' as metric
FROM
cvn
JOIN
tblvendorindex ON tblvendorindex.vendorindexid = CVN.vendorindexid
INNER JOIN
tblloadingmonths ON tblloadingmonths.month = CVN.month
Im getting different results for this converted query. Any guidance would be greatly appreciated
You are taught correctly in that you should list your join clause (ON...) and the second query is obviously far more readable and is preferred. Similarly, old-style joins simply list everything in the WHERE clause for INNER JOIN but again, this is hard to read. Regarding your different results. They are different because
cvn table name is different from tblcvn meaning it's a different object. If that was a type-o then...
In the first you LEFT JOINing to the tblloadingmonths and tblloadingmonths tables... meaning the rows must exist in both of those (for your join clause) for tblcvn rows to be returned. However, since it's a LEFT JOIN, the rows for tblloadingmonths and tblloadingmonths will be returned regardless of the match in tblcvn. In the second, you are using cvn as the base table and using INNER JOIN throughout. This means that the match must exists for the join clause for the rows in cvn to be returned. Otherwise, they would be filtered.
To recap, when using LEFT JOIN...
The table in the FROM clause matters. Swapping it with a LEFT JOIN table could change the results (as you witnessed)
Criteria in a WHERE clause could turn the LEFT into an INNER join.
I can't tell you if MySQL automatically assigns a join based on key assignments, or if it's making a Cartesian product. When using JOIN in SQL Server you have to list the ON clause. You could use old style joins... FROM Table1, Table2... but this should get you as Cartesian without a WHERE clause. This should get you close with some edits on your part:
SELECT
CVN.[Supplier Confirmed Orders] + CVN.[Log Tech Confirmed Orders] AS 'orders confirmed',
(CVN.[Orders in CVN] - CVN.[Cancelled Orders]) AS 'Orders in CVN',
tblloadingmonths.month,
tblvendorindex.vendorindexid,
'Service' AS category,
'CVN Compliance' as metric
FROM
tblvendorindex
INNER JOIN
tblloadingmonths ON tblvendorindex.??? = tblloadingmonths.???? --find out what the relation is, a foreign key perpahs. Would need a data model to determine.
LEFT JOIN
cvn ON tblloadingmonths.month = cnv.month
AND tblvendorindex.vendorindexid = cvn.vendorindexid
Thanks to your comments, you confirmed the MySQL join was producing a Cartesian Product implicitly which you can achieve with a CROSS JOIN explicitly in SQL Server, as you answered.
SELECT
CVN.[Supplier Confirmed Orders] + CVN.[Log Tech Confirmed Orders] AS 'orders confirmed',
(CVN.[Orders in CVN] - CVN.[Cancelled Orders]) AS 'Orders in CVN',
tblloadingmonths.month,
tblvendorindex.vendorindexid,
'Service' AS category,
'CVN Compliance' as metric
FROM
tblvendorindex
CROSS JOIN tblloadingmonths
LEFT JOIN
cvn ON tblloadingmonths.month = cnv.month
AND tblvendorindex.vendorindexid = cvn.vendorindexid
I have come up with two queries, both use an inner join on two different tables.
Query 1
SELECT PRODUCTS.CODE, PRODUCTS.REFERENCE, PRODUCTS.TAXCAT, PRODUCTS.DISPLAY,PRODUCTS.NAME, PRODUCTS.PRICEBUY, PRODUCTS.PRICESELL, CATEGORIES.NAME AS CATEGORY
FROM PRODUCTS INNER JOIN CATEGORIES ON PRODUCTS.CATEGORY = CATEGORIES.ID;
Query 2
SELECT PRODUCTS.CODE, PRODUCTS.REFERENCE, PRODUCTS.TAXCAT, PRODUCTS.DISPLAY,PRODUCTS.NAME, PRODUCTS.PRICEBUY, PRODUCTS.PRICESELL,STOCKCURRENT.UNITS AS UNIT FROM PRODUCTS INNER JOIN STOCKCURRENT ON STOCKCURRENT.PRODUCT = PRODUCTS.ID;
Both queries run fine on their own, when I try to use both inner joins together I get errors. This is what I came up with on my own. I'm having trouble understanding the syntax to achieve this.
SELECT PRODUCTS.CODE, PRODUCTS.REFERENCE, PRODUCTS.TAXCAT,
PRODUCTS.DISPLAY,PRODUCTS.NAME, PRODUCTS.PRICEBUY,
PRODUCTS.PRICESELL,STOCKCURRENT.UNITS AS UNIT FROM PRODUCTS INNER JOIN
STOCKCURRENT ON STOCKCURRENT.PRODUCT = PRODUCTS.ID, CATEGORIES.NAME AS
CATEGORY FROM PRODUCTS INNER JOIN CATEGORIES ON PRODUCTS.CATEGORY =
CATEGORIES.ID;
Thank you.
Your attempted query has several syntax problems. Assuming you just want to join together the three tables, you may try the following query:
SELECT
p.CODE,
p.REFERENCE,
p.TAXCAT,
p.DISPLAY,
p.NAME,
p.PRICEBUY,
p.PRICESELL,
s.UNITS AS UNIT,
c.NAME AS CATEGORY
FROM PRODUCTS p
INNER JOIN STOCKCURRENT s
ON s.PRODUCT = p.ID
INNER JOIN CATEGORIES c
ON p.CATEGORY = c.ID;
Note that I introduced table aliases here. These aliases can be used elsewhere in the query to avoid having to repeat the entire table name.
By the way, I can also see taking a union of your two original queries. But without expected output, it was not entirely clear what you want.
use classicmodels;
select Orders.OrderNumber,
Customers.CustomerName, Orders.Status, orders.shippeddate,
Customers.Country
from Customers **cross join/inner join** Orders
on Customers.CustomerNumber = Orders.customerNumber
order by 1 asc
Hi all, I'm really confused as to why inner join in my query isn't really any different from the result of the cross join? I thought that cross join would result of a Cartesian product but both joins are giving me 326 rows. I've also seen somewhere that I shouldn't use non-unique data?
From the MySQL JOIN docs:
In MySQL, JOIN, CROSS JOIN, and INNER JOIN are syntactic equivalents
(they can replace each other). In standard SQL, they are not
equivalent. INNER JOIN is used with an ON clause, CROSS JOIN is used
otherwise.
I've got a serious problem with a nested query, which I suspect MySQL is interpreting as a correlated subquery when in fact it should be uncorrelated. The query spans two tables, one being a list of products and the other being their price at various points in time. My aim is to return each price record for products that have a price range above a certain value for the whole time. My query looks like this:
SELECT oP.id, oP.title, oCR.price, oC.timestamp
FROM Crawl_Results AS oCR
JOIN Products AS oP
ON oCR.product = oP.id
JOIN Crawls AS oC
ON oCR.crawl = oC.id
WHERE oP.id
IN (
SELECT iP.id
FROM Products AS iP
JOIN Crawl_Results AS iCR
ON iP.id = iCR.product
WHERE iP.category =2
GROUP BY iP.id
HAVING (
MAX( iCR.price ) - MIN( iCR.price )
) >1
)
ORDER BY oP.id ASC
Taken alone, the inner query executes fine and returns a list of the id's of the products with a price range above the criterion. The outer query also works fine if I provide a simple list of ids in the IN clause. When I run them together however, the query takes ~3min to return ~1500 rows, so I think it's executing the inner query for every row of the outer, which is not ideal. I did have the columns aliased the same in the inner and outer queries, so I thought that aliasing them differently in the inner and outer as above would fix it, but it didn't.
Any ideas as to what's going on here?
MySQL might think it could use indexes to execute the query faster by running it once for every OP.id. The first thing to check is if your statistics are up to date.
You could rewrite the where ... in as a filtering inner join. This is less likely to be "optimized" for seeks:
SELECT *
FROM Crawl_Results AS oCR
JOIN Products AS oP
ON oCR.product = oP.id
JOIN Crawls AS oC
ON oCR.crawl = oC.id
JOIN (
SELECT iP.id
FROM Products AS iP
JOIN Crawl_Results AS iCR
ON iP.id = iCR.product
WHERE iP.category =2
GROUP BY
iP.id
HAVING (MAX(iCR.price) - MIN(iCR.price)) > 1
) filter
ON OP.id = filter.id
Another option is to use a temporary table. You store the result of the subquery in a temporary table and join on that. That really forces MySQL not to execute the subquery as a correlated query.