How connect two select? - sql

I have a problem with select from two table.
I use filtr from date, when I used NOT IN but didn't work, because data to result not in second table. I want display outfits which is free in these date and outfits which not in table rent.
Structure of base in the picture:
SELECT o.Id, o.Name, c.Name, o.Description,o.Price, r.Date1, r.Date2, r.Return
FROM Outfit o INNER JOIN
Category c
ON o.Category = c.Id INNER JOIN
Rent r
ON o.Id = r.OutFit
WHERE (myfiltrdate NOT BETWEEN r.Date1 AND r.Date2) OR
r.Return IS NOT NULL
Now my result are only record/outfit which are Rent table, but I want this result and Outfit which are not in table Rent

You may try a left join -
SELECT o.Id, o.Name, c.Name, o.Description,o.Price, r.Date1, r.Date2, r.Return
FROM Outfit o LEFT JOIN
Category c
ON o.Category = c.Id INNER JOIN
Rent r
ON o.Id = r.OutFit
WHERE (myfiltrdate NOT BETWEEN r.Date1 AND r.Date2) OR
r.Return IS NULL

I think you want LEFT JOINs and filtering. Something like this:
SELECT o.Id, o.Name, c.Name, o.Description, o.Price,
r.Date1, r.Date2, r.Return
FROM Outfit o LEFT JOIN
Category c
ON o.Category = c.Id LEFT JOIN
Rent r
ON o.Id = r.OutFit AND
(myfiltrdate BETWEEN r.Date1 AND r.Date2)
WHERE r.Return IS NULL;

Change your query to left join and filter the dates like this:
SELECT o.Id, o.Name, c.Name, o.Description,o.Price, r.Date1, r.Date2, r.Return
FROM Outfit o
INNER JOIN Category c ON o.Category = c.Id
LEFT JOIN Rent r ON o.Id = r.OutFit
WHERE (myfiltrdate < r.Date1 AND myfiltrdate > r.Date2) OR
r.Return IS NOT NULL
I don't have clear if Return is a date which the outfit is returned or is a boolean but I suspect that the condition must be
And r.Return IS NOT NULL

Related

Select every value (even when it is null) with inner join sql

This is my sql select statment
SELECT k.name, c.name AS nameCustomer, o.*
FROM offertes o
INNER JOIN customers k
ON o.idCustomer= k.id
INNER JOIN contactperson c
ON o.idContact = c.id;
When o.idContact doesn't exist, then there will be no values selected. I wan't to get NULL instead of nothing. It still need to SELECT the whole row! Can anyone help me?
ps. I think it's going wrong with the inner join (ON o.idContact = c.id);
Try this:
Replace your last INNER JOIN with LEFT JOIN.
Using LEFT JOIN you tell my main table (offertes) returns always result but if in secondary table (contactperson) there's no row matches returns NULL all fields of that table
SELECT k.name, c.name AS nameCustomer, o.*
FROM offertes o
INNER JOIN customers k
ON o.idCustomer= k.id
LEFT JOIN contactperson c
ON o.idContact = c.id;
You'll need an outer join instead.
e.g.
SELECT k.name, c.name AS nameCustomer, o.*
FROM customers k LEFT OUTER JOIN
(offertes o INNER JOIN
contactperson c
ON o.idContact = c.id)
ON o.idCustomer= k.id;
(I assume there'll be a counterpart of an offerte in contactperson, else you'll need an outer join there as well)
you need to rewrite a query using outer join
SELECT k.name, c.name AS nameCustomer, o.*
FROM customers k
LEFT OUTER JOIN offertes o ON o.idCustomer = k.id
LEFT OUTER JOIN contactperson c ON o.idContact = c.id;

Left join without using left join with 3 tables

I have to get all data from 3 tables with left join. I did that with and without using left join. But my teacher ask another solution that uses just inner join. I just couldn't find the solution please give some advice. Here are the tables:
And the results should look like this:
With left join solution:
SELECT O.*,C.CUST_CODE,C.CUST_NAME,P.PART_CODE,P.PART_NAME
FROM ORDERS 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
Without left join solution:
SELECT O.*,
(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,
(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
FROM ORDERS O
Here is one approach which uses only INNER JOIN and does not use LEFT JOIN anywhere. It begins with your original query using INNER JOIN instead of LEFT JOIN, and then adds to that result set the pieces which are missing from taking the inner product of all the tables.
SELECT t.* FROM
(
SELECT O.ORDER_ID, O.ORDER_DATE, C.CUST_CODE, C.CUST_NAME, P.PART_CODE, P.PART_NAME
FROM ORDERS O
INNER JOIN PART P
ON P.PART_ID = O.PART_ID
INNER JOIN CUSTOMER C
ON C.CUST_ID = O.CUST_ID
UNION
SELECT O.ORDER_ID, O.ORDER_DATE, NULL AS CUST_CODE, NULL AS CUST_NAME, P.PART_CODE,
P.PART_NAME
FROM ORDERS O
INNER JOIN PART P
ON P.PART_ID = O.PART_ID
WHERE O.CUST_ID NOT IN (SELECT C.CUST_ID FROM CUSTOMER C)
OR O.CUST_ID IS NULL
UNION
SELECT O.ORDER_ID, O.ORDER_DATE, C.CUST_CODE, C.CUST_NAME, NULL AS PART_CODE,
NULL AS PART_NAME
FROM ORDERS O
INNER JOIN CUSTOMER C
ON C.CUST_ID = O.CUST_ID
WHERE O.PART_ID NOT IN (SELECT P.PART_ID FROM PART P)
OR O.PART_ID IS NULL
UNION
SELECT O.ORDER_ID, O.ORDER_DATE, NULL AS CUST_CODE, NULL AS CUST_NAME,
NULL AS PART_CODE, NULL AS PART_NAME
FROM ORDERS O
WHERE (O.CUST_ID NOT IN (SELECT C.CUST_ID FROM CUSTOMER C) AND
O.PART_ID NOT IN (SELECT P.PART_ID FROM PART P)) OR
(O.CUST_ID IS NULL AND O.PART_ID IS NULL)
) t
ORDER BY t.ORDER_ID ASC
Follow the link below for a working demo:
SQLFiddle
This makes no sense in "real life", but I understand it's meaningfulness in a SQL course. You have a good teacher.
Try like this
SELECT * FROM
(
SELECT O.*,C.CUST_CODE,C.CUST_NAME,P.PART_CODE,P.PART_NAME
FROM ORDERS O
INNER JOIN PART P ON P.PART_ID = O.PART_ID
INNER JOIN CUSTOMER C ON C.CUST_ID = O.CUST_ID
UNION
SELECT O.*,NULL,NULL,P.PART_CODE,P.PART_NAME
FROM ORDERS O
INNER JOIN PART P ON P.PART_ID = O.PART_ID
WHERE O.CUST_ID IS NULL
UNION
SELECT O.*,C.CUST_CODE,C.CUST_NAME,NULL, NULL
FROM ORDERS O
INNER JOIN CUSTOMER C ON C.CUST_ID = O.CUST_ID
WHERE O.PART_ID IS NULL
UNION
SELECT O.*,NULL,NULL,NULL, NULL
FROM ORDERS O
WHERE O.PART_ID IS NULL AND O.CUST_ID IS NULL
) T
ORDER BY ORDER_ID

AVG of AVG, aggregate functions of subquery

This subquery produces the correct table. But now I want to get the average of the averages, and I'm getting an error "Missing FROM-clause entry for table "c"".
SELECT
c.name,
AVG(avgvalue)
FROM
(
SELECT
c.name,
p.name,
AVG(a."value") AS avgvalue
FROM answers a INNER JOIN survey_responses sr ON sr.id = a.survey_response_id AND a.question_id = 13
INNER JOIN answers category_answer ON category_answer.survey_response_id = sr.id AND category_answer.question_id = 264
INNER JOIN answers_categories ac ON category_answer.id = ac.answer_id
INNER JOIN categories c ON c.id = ac.category_id
INNER JOIN products p ON p.id = a.product_id
WHERE c.name IN ('Accounting')
GROUP BY c.name, p."name"
HAVING count(p.name)>10
) as ProductAverages
GROUP BY c.name;
You are naming the ProductAverages, so your table aliases should reference it, not c - which can be used only in the inner query:
SELECT
name, -- Here
AVG(avgvalue)
FROM
(
SELECT
c.name,
p.name,
AVG(a."value") AS avgvalue
FROM answers a INNER JOIN survey_responses sr ON sr.id = a.survey_response_id AND a.question_id = 13
INNER JOIN answers category_answer ON category_answer.survey_response_id = sr.id AND category_answer.question_id = 264
INNER JOIN answers_categories ac ON category_answer.id = ac.answer_id
INNER JOIN categories c ON c.id = ac.category_id
INNER JOIN products p ON p.id = a.product_id
WHERE c.name IN ('Accounting')
GROUP BY c.name, p."name"
HAVING count(p.name)>10
) as ProductAverages
GROUP BY name; -- and here

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

order sql query by name

I have a query which I would like to tweak little bit to display different info.
Currently my query gets all the orders with products ranked by the one with most conversions at the top.
Here is the query:
SELECT nopv.ProductVariantID, COUNT(nopv.ProductVariantID), p.ProductId, c.CategoryID, c.Name FROM Nop_OrderProductVariant nopv
INNER JOIN Nop_ProductVariant npv
ON nopv.ProductVariantID = npv.ProductVariantId
INNER JOIN Nop_Product p
ON npv.ProductID = p.ProductId
INNER JOIN Nop_Product_Category_Mapping npcm
ON p.ProductId = npcm.ProductID
INNER JOIN Nop_Category c
ON npcm.CategoryID = c.CategoryID
GROUP BY nopv.ProductVariantID, p.ProductId, c.CategoryID, c.Name
HAVING COUNT(*) > 0
ORDER BY COUNT(nopv.ProductVariantID) DESC
What I have as a result is:
I want to be able to have each category only one time, for example "programmers & modules" category should only one record, containing the sum of all the productvariantIDs in that category. The first field can be avoided as well, because if there are multiple productvariants, the query will need to show just one. What I really need is the count of each category and the categoryID.
Thanks in advance, Laziale
Simply remove the Variant and ProductID from both the select and Group By.
SELECT
COUNT(nopv.ProductVariantID) ,
c.CategoryID ,
c.Name
FROM
Nop_OrderProductVariant nopv
INNER JOIN Nop_ProductVariant npv
ON
nopv.ProductVariantID = npv.ProductVariantId
INNER JOIN Nop_Product p
ON
npv.ProductID = p.ProductId
INNER JOIN Nop_Product_Category_Mapping npcm
ON
p.ProductId = npcm.ProductID
INNER JOIN Nop_Category c
ON
npcm.CategoryID = c.CategoryID
GROUP BY
c.CategoryID ,
c.Name
HAVING
COUNT(*) > 0
ORDER BY
COUNT(nopv.ProductVariantID) DESC
I think the issue is your group by:
GROUP BY nopv.ProductVariantID, p.ProductId, c.CategoryID, c.Name
Try:
GROUP BY c.CategoryID, c.Name -- c.Name is here since you probably can't select it otherwise
Then make whatever changes you need to your SELECT so it will work.
So something like this:
SELECT COUNT(nopv.ProductVariantID), c.CategoryID, c.Name
FROM Nop_OrderProductVariant nopv
INNER JOIN Nop_ProductVariant npv
ON nopv.ProductVariantID = npv.ProductVariantId
INNER JOIN Nop_Product p
ON npv.ProductID = p.ProductId
INNER JOIN Nop_Product_Category_Mapping npcm
ON p.ProductId = npcm.ProductID
INNER JOIN Nop_Category c
ON npcm.CategoryID = c.CategoryID
GROUP BY c.CategoryID, c.Name
HAVING COUNT(*) > 0
ORDER BY COUNT(nopv.ProductVariantID) DESC