Joining complex sql oracle select queries - sql

I have a complex query that selects product id values from history and orders.
SELECT ProductID
FROM History h ( SELECT .....) LATEST
WHERE h.ProductId = LATEST.ProductID
AND ....
AND IsActive = true;
This query is too long, so I could not write all of it. But it returns a table like this:
ProdutID
--------
4654654
9879879
5465465
2132188
7894215
....
I want to join this product id result another table that containts ProductId column.
SELECT * FROM MySecondTable;
ProductID Color
--------- -----
4654654 red
9879879 blue
5465465 orange
How can I join these two query?

CTEs are a really simple way to do such a thing:
with t as (<your query here>)
select t.*, t2.color
from t join
MySecondTable t2
on t.ProductId = t2.ProductId;
You could also just add the join to the from clause of the original query.

you could use the firts as inner joined table
SELECT b.*
FROM MySecondTable b
INNER JOIN (
SELECT ProductID
FROM History h ( SELECT .....) LATEST
WHERE h.ProductId = LATEST.ProductID
AND ....
AND IsActive = true;
) t on t.ProductID = b.ProductID

Related

How can I perform this sql update using sql instead of using code?

I have been able to select this data, using these two sql queries
Query 1:
SELECT article_id, amount_required, amount_sold FROM products_articles,sales WHERE sales.product_id = products_articles.product_id
Query 2:
SELECT * FROM articles
What I want to do, is go through the first table (with amount sold and required) (it's fine that there are duplicate rows), and for each row in the table multiply the value of amount_sold and amount_required and then subtract that value from amount_in_stock where the ids match in the second table.
Example from the first row:
2 * 4 = 8, change amount_in_stock from 124 to 116.
And so on...
How can I do this using just sql?
UPDATE A
SET
A.amount_in_stock =(S.amountSold * S.amount_required)- A.amount_in_stock
FROM articles AS A
INNER JOIN
products_articles AS PA
ON PA.article_id= A.article_id
INNER JOIN Sales AS S
ON S.product_id=PA.product_id
Please try this:
Update articles a
inner join
(
SELECT article_id, sum(amount_required) amount_required, sum(amount_sold )amount_sold FROM products_articles inner join sales on sales.product_id = products_articles.product_id
group by article_id
)b on a.article_id=b.article_id
set a.amount_in_stock=a.amount_in_stock-(amount_required*amount_sold )
Since there could be multiple rows in product_articles and amount_sold I have used group by to sum the amounts.
For SQLite please try this:
Update articles
set amount_in_stock=(SELECT sum(amount_required) * sum(amount_sold ) FROM products_articles inner join sales on sales.product_id = products_articles.product_id
where products_articles.article_id=articles.article_id
group by article_id
)
where exists (SELECT * FROM products_articles inner join sales on sales.product_id = products_articles.product_id where products_articles.article_id=articles.article_id
)

Returning ID's from two other tables or null if no IDs found using using a left join SQL Server

I am wondering if someone could hep me. I am trying to make a join on two tables and return an id if an id is there but if there is no id return null but still return the row for that product and not ignore it. My query below returns twice the amount the records to which I can not figure out why.
SELECT
T2.ProductID, FirstChild.SupplierID, SecondChild.AccountID
FROM
Products T2
LEFT OUTER JOIN
(
SELECT TOP(1) SupplierID, Reference,CompanyID, Row_Number() OVER (Partition By SupplierID Order By SupplierID) AS RowNo FROM Suppliers
)
FirstChild ON T2.SupplierReference = FirstChild.Reference AND RowNo = 1AND FirstChild.CompanyID =T2.CompanyID
LEFT OUTER JOIN
(
SELECT TOP(1) AccountID, SageKey,CompanyID, Row_Number() OVER (Partition By AccountID Order By AccountID) AS RowNo2 FROM Accounts
)
SecondChild ON T2.ProductAccountReference = SecondChild.Reference AND RowNo2 = 1 AND SecondChild.CompanyID =T2.CompanyID
Example of what I am trying to do
ProductID SupplierID AccountID
1 5 2
2 6 NULL
3 NULL NULL
OUTER APPLY and ditching the ROW_NUMBER Seems like a better choice here:
SELECT
p.ProductId
,FirstChild.SupplierId
,SecondChild.AccountId
FROM
Products p
OUTER APPLY (SELECT TOP (1) s.SupplierId
FROM
Suppliers s
WHERE
p.SupplierReference = s.SupplierReference
AND p.CompanyId = s.CompanyId
ORDER BY
s.SupplierId
) FirstChild
OUTER APPLY (SELECT TOP (1) a.AccountId
FROM
Accounts
WHERE
p.ProductAccountReference = a.Reference
AND p.CompanyId = a.CompanyId
ORDER BY
a.AccountID
) SecondChild
The way your query is written above there is no correlation for the derived tables. Which means you would always get what ever SupplierId SQL chooses based on optimization and if that doesn't happen to always be Row1 you wont get the value. You need to relate your Table and select top 1, adding an ORDER BY in your derived table is like identifying the row number you want.
If it's just showing duplicate records, wouldn't an inelegant solution just be to add distinct in the select line?

sql optimize a query using the join

I have a table productHistory
productHistory (id_H , id_product , name , tsInsert);
I wanna get from the table productHistory the last product in the giving period (start, end):
tsInsert must be between the start and the end.
I can do like this:
select max(id_H)
from productHistory
where tsInsert>=:start and tsInsert <=:end
group by id_product;
then select all from productHistory where id_H in the previous selection.
This query is very heavy, is there any other solution using the right join for example?
I tried this solution:
SELECT * FROM productHistory x
INNER JOIN
(
SELECT MAX(id_H) as maxId
FROM productHistory
GROUP id_product
) y
ON x.id_H = y.maxId
and x.TSINSERT >=:start and x.TSINSERT <=:end

Joining to the same table in SQL - SQL Server 2008

I have the following table:
ID Type Description IDOfSystem
--------------------------------
1000 Company Company Item NULL
1010 System System Item NULL
1020 Company NULL 1010
I have System and Company Items. I need to write a select query that gets all the company items and system items UNLESS if a company item has a value in IDOfSystem I need to exclude that system item and get the description from the system item.
So, given the above table, the SQL select should return rows 1000, 1020 (with "System Item") as the description.
If 1020 didn't exist, I'd simply get 1000 and 1010.
I guess I can break this up into multiple queries and do a UNION. I tried to do a left outer join on the same table but couldn't get the description from the system row.
Any help?
SELECT ID, Type, Description
FROM MyTable AS A
WHERE IDOfSystem IS NULL AND NOT EXISTS (SELECT *
FROM MyTable AS B
WHERE B.IDOfSystem = A.ID)
UNION ALL
SELECT A.ID, A.Type, B.Description
FROM MyTable AS A INNER JOIN MyTable AS B ON A.IDOfSystem = B.ID
WHERE IDOfSystem IS NOT NULL
What I'm doing is first selecting all rows that don't have a referenced system, and aren't used as some other rows system.
Then I'm doing a union with another query that finds all rows with a referenced system, and joining in the system to grab it's description.
SELECT
Companies.ID
,Companies.Type
,COALESCE(Systems.Description, Companies.Description) as Description
FROM YourTable Companies
LEFT OUTER JOIN YourTable Systems on Systems.ID = Companies.IDOfSystem
WHERE NOT EXISTS
(
SELECT * FROM YourTable T3 WHERE T3.IDOfSystem = Companies.ID
)
Here it is running on SEDE.
This approach uses a self join to look up the corresponding system's description. A separate subquery filters out the referenced systems.
select yt1.Id
, yt1.Type
, coalesce(yt2.Description, yt1.Description) as Description
from YourTable yt1
left join
YourTable yt2
on yt1.type = 'Company'
and yt2.type = 'System'
and yt2.ID = yt1.IDOfSystem
where yt1.type in ('System', 'Company')
and not exists
(
select *
from YourTable yt3
where yt1.type = 'System'
and yt3.type = 'Company'
and yt1.ID = yt3.IDOfSystem
)
Working example at SE Data.
I'm sure there are better ways of doing this, but try:
SELECT A.Id, A.Type, ISNULL(A.Description,B.Description) Description, A.IDOfsystem
FROM YourTable A
LEFT JOIN YourTable B
ON A.IDOFSystem = B.ID
WHERE A.ID NOT IN (SELECT IDOfsystem FROM YourTable WHERE IDOfsystem IS NOT NULL)

sql server top query

I don't know what's wrong with this query :
select * from products , top 1 * from pic
where products.productId = pic.productId
I have Products and Pic tables , every products could have 1 to n pic and I would like to return every product and the first pic of that
The picture of diagram may help
You need to have a way of uniquely identifying each pic, so I'm asuming that table as an ID column...
SELECT
*
FROM
products
LEFT JOIN
pic
ON pic.Id = (SELECT TOP 1 id FROM pic WHERE productID = products.ProductID ORDER BY id DESC)
EDIT
Inspired by another answer, using APPLY instead...
SELECT
*
FROM
products
OUTER APPLY
(SELECT TOP 1 * FROM pic WHERE productID = products.ProductID ORDER BY id DESC) AS pic
You need a subquery to
select the first PicID's for each ProductID
join with Pic table itself to get the additional columns
join with Products to get the product columns
SQL Statement
SELECT *
FROM Products prod
LEFT OUTER JOIN Pic p ON p.ProductID = prod.ProductID
LEFT OUTER JOIN (
SELECT PicID = MIN(PicID)
, ProductID
FROM Pic
GROUP BY
ProductID
) pm ON pm.PicID = p.PicID
There is also way with subsection but please avoid sub select as much as You can in yours TSQL
Select
*
,(select top(1) adress from pic where pic.productid=products.id /* if u wanna you also can order by id */ ) as Id
from products