sql server: select a NULL field that is foreign key - sql

table "product" :
productID productNAME
21 mouse
22 keyboard
table "order" :
orderID productID
31 21
32 NULL
sql command:
SELECT dbo.[order].orderID, dbo.product.productNAME
FROM dbo.[order]
INNER JOIN dbo.product ON dbo.[order].productID = dbo.product.productID
result:
orderID productID
31 mouse
QUESTION:
how to show the second order? (while productID of that order is NULL, but that order existed)
is there any trick for that?
i tried these:
WHERE (dbo.[order].orderID = 32) OR
(dbo.product.productID IS NULL)
and
SELECT dbo.[order].orderID, ISNULL(dbo.product.productNAME, ' - ') AS Expr1
FROM dbo.[order]
INNER JOIN dbo.product ON dbo.[order].productID = dbo.product.productID
but the same result

The obvious solution is left join:
SELECT o.orderID, p.productNAME
FROM dbo.[order] o LEFT JOIN
dbo.product p
ON o.productID = p.productID;
You could also write:
SELECT o.orderID, p.productNAME
FROM dbo.[order] o JOIN
dbo.product p
ON o.productID = p.productID OR o.productID IS NULL;
The OR will probably affect the performance of this query.

It's because you're using an Inner Join, specifically matched on ProductID. Because one is NULL of course it will not match. If you wish to return all results from the Order table regardless of whether there is a match in the product table, you need to look at other types of Joins, such as LEFT and RIGHT OUTER JOINS.

A classic outer join example!
SELECT dbo.[order].orderID, ISNULL(dbo.product.productNAME, ' - ') AS Expr1
FROM dbo.[order]
LEFT JOIN dbo.product ON dbo.[order].productID = dbo.product.productID

you have to use OR condition along with inner join.
SELECT o.orderID
,p.productNAME
FROM dbo.[order] o
INNER JOIN dbo.product p ON o.productID = p.productID
OR o.productID IS NULL;

The obvious/classic solution is UNION:
SELECT dbo.[order].orderID, dbo.product.productNAME
FROM dbo.[order]
INNER JOIN dbo.product ON dbo.[order].productID = dbo.product.productID
UNION
SELECT dbo.[order].orderID, '{{NONE}}' AS productNAME
FROM dbo.[order]
WHERE dbo.[order].productID IS NULL;

Related

Two subqueries in a with statement and a select statement for the outcome

with pro_cra as (
select p.productid
from production.product p
where p."name" like 'Crankset'
),
add_lon as (
select a.addressid
from person.address a
where city like 'London'
)
select sum(s1.orderqty)
from sales.salesorderdetail s
join sales.salesorderheader s1 on s.salesorderid = s1.salesorderid
join add_lon adl on s.billtoaddress = adl.addressid
join pro_cra prc on s.productid = prc.productid
;
)
Hi guys !
I know my problem is in the last join statements. I don't know what the solution is. Can anybody help?
Update! I deleted those select statements I had. I used to check the tables they werent relevant for the code.
I get this message.
SQL Error [42P01]: ERROR: relation "add_lon" does not exist
Position: 133
Try this:
with pro_cra as (
select p.productid from production.product p
where p."name" like 'Crankset'),
add_lon as (
select a.addressid from person.address a
where city like 'London')
select sum(s1.orderqty) from sales.salesorderdetail s
join sales.salesorderheader s1 on s.salesorderid = s1.salesorderid
join add_lon adl on s.billtoaddress = adl.addressid
join pro_cra prc on s.productid = prc.productid;
removed the select * statements with semicolons and also moved the final semi-colon to its proper place.
Does this work?

Insufficient output from SQL query

I'm using the northwind db: http://dev.assets.neo4j.com.s3.amazonaws.com/wp-content/uploads/Northwind_diagram.jpg
I have to output all orders placed by CustomerID ALFKI with more than one unique product. I get the correct orders out, but I can't figure out why it's only printing one product name per order.
My query:
SELECT a.OrderID, p.ProductName
FROM Products p
INNER JOIN 'Order Details' a
ON (p.ProductID = a.ProductID)
INNER JOIN Orders b
ON (a.OrderID = b.OrderID)
WHERE (b.CustomerID = 'ALFKI')
GROUP BY a.OrderID
HAVING COUNT(DISTINCT a.ProductID) > 1
You need the GROUP BY and HAVING to be part of a subquery, with your primary query selecting the detail using the list of OrderIDs returned from the subquery as filter criteria. Try the following syntax for T-SQL:
SELECT
a.OrderID,
p.ProductName
FROM
Products p
INNER JOIN [Order Details] a
ON (p.ProductID = a.ProductID)
INNER JOIN Orders b
ON (a.OrderID = b.OrderID)
WHERE
a.OrderID IN
(
SELECT a.OrderID
FROM [Order Details] a
INNER JOIN Orders b
ON (a.OrderID = b.OrderID)
WHERE (b.CustomerID = 'ALFKI')
GROUP BY a.OrderID
HAVING COUNT(DISTINCT a.ProductID) > 1
)

Update table based on a select from another

I have this select statement below which I would like to use to update the quantity of the products in another table, tablex. I cannot seem to figure out how to match the product number from this query to the productnumber tablex and then add the quantity found in this statement to the existing quantity in tablex.
select
p.ProductNumber, sod.Quantity ,so.StateCode
from
SalesOrderDetail sod
right join
ProductAssociation pa on sod.ProductId = pa.ProductId
left join
Product p on pa.AssociatedProduct = p.ProductId
left join
SalesOrder so on so.SalesOrderId = sod.SalesOrderId
where
so.StateCode = '3'
You can have update base on multiple tables, the syntax is something like
update tablex
set tablex.quantity = sod.Quantity
from tablex join product p on tablex.productnumber = p.ProductNumber
join... -- add the rest of your joins and conditions.
I'm guessing that you're trying to update a large quantity of rows in TableX so I'm going to suggest a way to do them all at once rather than one at a time.
update TableX
set quantity = quantity +
(select sod.quantity from SalesOrderDetail where sod.ProductId = TableX.ProductId)
You might wish to do this on a subset of SalesOrderDetail, and that's fine, just use the WHERE clause for that.
Try
UPDATE tablex
SET Quantity= Quantity +
(SELECT sod.Quantity FROM SalesOrderDetail sod
RIGHT JOIN ProductAssociation pa ON sod.ProductId=pa.ProductId
LEFT JOIN Product p ON pa.AssociatedProduct=p.ProductId
LEFT JOIN SalesOrder so ON so.SalesOrderId=sod.SalesOrderId
WHERE so.StateCode='3' AND p.ProductNumber=Tablex.productnumber)
Are you looking for this?
UPDATE tx SET tx.Quantity = tx.Quantity + sod.Quantity FROM
from SalesOrderDetail sod
right join ProductAssociation pa on sod.ProductId=pa.ProductId
left join Product p on pa.AssociatedProduct=p.ProductId
left join SalesOrder so on so.SalesOrderId=sod.SalesOrderId
left join tablex tx on p.ProductNumer = tx.ProductNumber
where so.StateCode='3'
How can I do an UPDATE statement with JOIN in SQL?
Basic syntax for UPDATE with a JOIN:
UPDATE A
SET A.foo = B.bar
FROM TableA A
JOIN TableB B
ON A.col1 = B.colx
So I believe you're after something like:
UPDATE A
SET A.Quantity = B.Quantity + A.Quantity
FROM Tablex A
JOIN (select p.ProductNumber, sod.Quantity ,so.StateCode
from SalesOrderDetail sod
right join ProductAssociation pa on sod.ProductId=pa.ProductId
left join Product p on pa.AssociatedProduct=p.ProductId
left join SalesOrder so on so.SalesOrderId=sod.SalesOrderId
where so.StateCode='3'
)B
ON A.ProductNumber = B.ProductNumber
Not sure how your StateCode factors in, additional JOIN criteria perhaps?

LEFT OUTER JOIN EQUIVALENT

I have a tables contains null values. In ORDER table i have 2 null in PART_ID section and 2 null values in CUSTOMER_ID.
And i have that kind of query:
SELECT O.ORDER_ID , O.ORDER_DATE , O.CUST_ID, O.QUANTITY ,O.PART_ID ,
C.CUST_NAME, C.CUST_CODE, P.PART_NAME, P.PART_CODE
FROM [ORDER] O
LEFT OUTER JOIN PART P ON P.PART_ID = O.PART_ID
LEFT OUTER JOIN CUSTOMER C ON C.CUST_ID = O.CUST_ID
So here is my question. How can i do it without using outer join ?
I tried too many things including where not exists or this ;
SELECT *
FROM [ORDER] O ,CUSTOMER C, PART P
WHERE C.CUST_ID = (
SELECT CUST_ID FROM CUSTOMER C WHERE O.CUST_ID = C.CUST_ID
) AND P.PART_ID = (SELECT PART_ID FROM PART P WHERE O.PART_ID = P.PART_ID)
but i couldn't find solution. If there is a solution how it will be ?
(Note: this is homework.)
I have that kind of table :
and left outer join gives that :
the hw said do it without using outer join and get same table as left outer join gives. But like a said i coulnd't. I'm also using MSSQL.
Outer join produces super-set over inner join. Indeed, from Wikipedia: A left outer join returns all the values from an inner join plus all values in the left table that do not match to the right table.
So to model left outer join using inner join one could use UNION of inner join SELECT between same tables with same join condition and another SELECT from 1st table that returns all rows without a match from the right table (I reduced your case to a single left join):
SELECT O.ORDER_ID , O.ORDER_DATE , O.CUST_ID, O.QUANTITY ,O.PART_ID ,
P.PART_NAME, P.PART_CODE
FROM [ORDER] O JOIN PART P ON P.PART_ID = O.PART_ID
UNION
SELECT O.ORDER_ID , O.ORDER_DATE , O.CUST_ID, O.QUANTITY ,O.PART_ID ,
NULL, NULL
FROM [ORDER] O
WHERE NOT EXISTS (SELECT 'found' FROM PART P WHERE P.PART_ID = O.PART_ID)
Presumably, you want to get matches to the columns with NULL values, instead of having them fail. If so, just modify the join conditions:
FROM [ORDER] O
LEFT OUTER JOIN PART P
ON P.PART_ID = O.PART_ID or (p.Part_id is NULL and o.Part_id is null)
LEFT OUTER JOIN CUSTOMER C
ON C.CUST_ID = O.CUST_ID or (c.cust_id is null and o.cust_id is null)
The major issue with this approach is that many (most?) SQL engines will not use indexes for the join.
Is there a specific reason why you don't want to use outer join? Isn't this the result you want? :
FROM [ORDER] O
LEFT JOIN PART P
ON P.PART_ID = O.PART_ID and P.PARTID is not null
LEFT JOIN CUSTOMER C
ON C.CUST_ID = O.CUST_ID and C.CUSTID is not null
So complete answer should be like this (after my teacher gave results) :
SELECT O.ORDER_ID,O.ORDER_DATE,O.CUST_ID,
(SELECT C.CUST_CODE FROM CUSTOMER C WHERE C.CUST_ID=O.CUST_ID) AS CUST_CODE,
(SELECT C.CUST_NAME FROM CUSTOMER C WHERE C.CUST_ID=O.CUST_ID) AS CUST_NAME,
O.PART_ID,
(SELECT P.PART_CODE FROM PART P WHERE P.PART_ID = O.PART_ID ) AS PART_CODE,
(SELECT P.PART_NAME FROM PART P WHERE P.PART_ID = O.PART_ID ) AS PART_NAME,
O.QUANTITY
FROM [ORDER] O

Select order products in MySQL from muliple tables

I have 3 tables:
orderProducts (orderId, productId, productValue),
products (productId, productName)
values (productId, productValue, productValuePrice).
I need to select order products (product id, name, value, price) with defined orderId.
How to do that with one MySQL query?
You could use a left join to return rows in the orderProducts table for which no corresponding rows in the other tables exist. Any missing columns will be NULL, allowing you to flag an error condition. The default join is an inner join, and will only return rows with matching entries in both joined tables.
select op.product id, p.name, v.productValue, p.productValuePrice
from orderProducts op
left join products p on p.productId = op.productId
left join values v
on v.productId = op.productId
and v.productValue = op.productValue
where op.orderId = <YourOrderId>
You can do this via a join, something like:
Select o.orderId, p.productId, p.name, o.productValue, v.productValuePrice
From products p
Join values v on p.productId = v.productId
Join orderProducts o on p.productId = o.orderId
Where orderId = 5
.......
select p.productId, p.productName, o.productValue, v.prodctValuePrice from orderProducts o join products p on o.productId = p.productId join values v on v.productId = p.productId where p.productId = 1