Select rows from table1 which don't have rows in table2 - sql-server

I have 2 tables, OrderTable & OrderDetailTable.
I am trying to select rows from OrderTable that don't have any rows in OrderDetailTable so we can Delete them.

I assume you have an id relation between the 2 tables:
select * from OrderTable
where orderdetails_id not in (select id from OrderDetailTable)
and to delete them
delete from OrderTable
where orderdetails_id not in (select id from OrderDetailTable)

SELECT o.*
FROM OrderTable o
LEFT JOIN OrderDetailTable od ON od.idOrderTable = o.id
WHERE od.id IS NULL;
od.id can be any field from OrderDetailTable that can't be null.

Suppose that OrderTable has a column id, and OrderDetailTable has a column orderTable_id
select * from OrderTable
WHERE id not in (
select ot.id from OrderTable ot inner join OrderDetailTable odt on odt.orderTable_id = ot.id
)

Related

Using sub-queries and filter in WHERE clause while joining tables

SELECT DISTINCT(t1.Ticker),t2.SecurityID,t2.ClosePrice,t2.QuoteDateTime FROM [Hub].[SecurityMaster].[SecurityMasterDetails] as t1
INNER JOIN [Hub].[SecurityMaster].[SecurityPrices] as t2
ON t2.SecurityID =t1.SecurityID
WHERE t2.QuoteDateTime IN (SELECT max(QuoteDateTime) FROM [Hub].[SecurityMaster].[SecurityPrices]) AND t1.SecurityTypeName = 'REIT'
I get an output with no data. The subquery doesn't run along with the other filter in the WHERE clause. I am not sure what I am doing wrong. Can somebody please help!
If you are trying to get the lastest row from SecurityPrices for each Ticker, one option is to use cross apply():
select --distinct /* distinct not needed if `Ticker` is unique on `smd`
smd.Ticker
, sp.SecurityID
, sp.ClosePrice
, sp.QuoteDateTime
from [Hub].[SecurityMaster].[SecurityMasterDetails] as smd
cross apply (
select top 1
i.SecurityID
, i.ClosePrice
, i.QuoteDateTime
from [Hub].[SecurityMaster].[SecurityPrices] i
where i.SecurityID = smd.SecurityID
order by i.QuoteDateTime desc
) as sp
where SecurityTypeName = 'REIT' /* which table does this column belong to? */
I think your query would be
SELECT DISTINCT TOP 1 WITH TIES
t1.Ticker,
t2.SecurityID,
t2.ClosePrice,
t2.QuoteDateTime
FROM [Hub].[SecurityMaster].[SecurityMasterDetails] as t1
INNER JOIN [Hub].[SecurityMaster].[SecurityPrices] as t2 ON t2.SecurityID =t1.SecurityID
WHERE SecurityTypeName = 'REIT'
ORDER BY t2.QuoteDateTime DESC
You aren't getting results because the max(QuoteDateTime) record doesn't have SecurityTypeName = 'REIT'. I think you want the max(QuoteDateTime) for this SecurityTypeName, so this can be done with an INNER JOIN.
SELECT DISTINCT
(t1.Ticker),
t2.SecurityID,
t2.ClosePrice,
t2.QuoteDateTime
FROM [Hub].[SecurityMaster].[SecurityMasterDetails] as t1
INNER JOIN [Hub].[SecurityMaster].[SecurityPrices] as t2
ON t2.SecurityID =t1.SecurityID
INNER JOIN
(SELECT max(QuoteDateTime) DT FROM [Hub].[SecurityMaster].[SecurityPrices]) P on P.DT = t2.QuoteDateTime
WHERE SecurityTypeName = 'REIT'
EDIT
Your data doesn't have what you think it does, I suspect. Here is how you can check...
--Find the SecurityID that matches the max date
SELECT
SecurityID ,
max(QuoteDateTime) DT
FROM [Hub].[SecurityMaster].[SecurityPrices]
GROUP BY SecurityID
--I'm betting this ID isn't in your SecurityMasterDetails where the Type is REIT
SELECT DISTINCT
SecurityID
FROM SecurityMasterDetails
WHERE SecurityTypeName = 'REIT'
Since the SecurityID returned in the first query isn't in the second query result set, you are going to get NULL results.

Why Inner Join worked as Cross Join in SQL Server?

I am trying to join several tables using INNER JOIN.
Here is code
IF OBJECT_ID('tempdb..#tmpRecData') IS NOT NULL
DROP TABLE #tmpRecData
--STEP 1
SELECT DISTINCT
pr.ChainID, pr.StoreID, pr.SupplierID, pr.ProductID,
MAX(CAST(pr.ActiveLastDate AS date)) AS 'Active Date'
--ChainID, SupplierID, StoreID, InvoiceDate, InvoiceNumber, SupplierInvoiceDate, SupplierInvoiceNumber
INTO
#tmpRecData
FROM
dbo.[ProductPrices_Retailer] AS pr
LEFT JOIN
ProductIdentifiers iden ON pr.ProductID = iden.ProductID
AND iden.ProductIdentifierTypeID = 2
WHERE
pr.ChainID = '119121'
AND pr.ActiveLastDate > '12/01/2016'
GROUP BY
pr.ProductID, pr.ProductName, iden.IdentifierValue,
pr.ChainID, pr.StoreID, pr.SupplierID
--STEP 2
SELECT
rec.ChainID, rec.StoreID, rec.SupplierInvoiceNumber,
rec.TransactionTypeID, rec.SupplierID, rec.SaleDateTime,
rec.ProductID, rec.UPC, rec.ProductDescriptionReported,
rec.RawProductIdentifier
FROM
#tmpRecData t
INNER JOIN
dbo.StoreTransactions AS rec WITH (NOLOCK) ON rec.ChainID = T.ChainID
WHERE
rec.ChainID = '119121'
DROP TABLE #tmpRecData
I am getting 4096 (Step1) * 145979 (Step2) = 725077693 rows (725 million)
This is a huge number of records, but I have used INNER JOIN, so why it worked as CROSS JOIN?
CROSS JOIN is very different to INNER JOIN.
INNER JOIN displays only the rows that have a match in both the joined tables..
CROSS JOIN produces a Cartesian product of the tables in the join. The number of rows of the result is the number of the rows in first table multiplied by the number of rows in the second table.
You need to join with store ID in step2 for this to work. It is running chainID for every store , hence too many number of records. If products also need to match, then you need to Join productID as well in step2
IF OBJECT_ID('tempdb..#tmpRecData') IS NOT NULL DROP TABLE #tmpRecData
--STEP 1
SELECT DISTINCT pr.ChainID,pr.StoreID,pr.SupplierID,pr.ProductID, MAX(CAST(pr.ActiveLastDate AS date)) AS 'Active Date'
--ChainID, SupplierID, StoreID, InvoiceDate, InvoiceNumber, SupplierInvoiceDate, SupplierInvoiceNumber
INTO #tmpRecData
FROM dbo.[ProductPrices_Retailer] AS pr
LEFT JOIN ProductIdentifiers iden
ON pr.ProductID=iden.ProductID
AND iden.ProductIdentifierTypeID=2
WHERE pr.ChainID='119121'
AND pr.ActiveLastDate>'12/01/2016'
GROUP BY pr.ProductID,pr.ProductName,iden.IdentifierValue,pr.ChainID,pr.StoreID,pr.SupplierID
--STEP 2
SELECT rec.ChainID,rec.StoreID,rec.SupplierInvoiceNumber,rec.TransactionTypeID,rec.SupplierID,rec.SaleDateTime,
rec.ProductID,rec.UPC,rec.ProductDescriptionReported,rec.RawProductIdentifier
FROM #tmpRecData t
INNER JOIN dbo.StoreTransactions AS rec WITH (NOLOCK)
ON rec.ChainID=T.ChainID and rec.StoreID = T.storeID
WHERE rec.ChainID='119121'
DROP TABLE #tmpRecData

Find rows only present in the result of one of two queries

I have two JOIN queries which give an output column of Id. How do I find all the Id values returned by query 1 but not returned by query 2?
select Id from Table1 join Table2;
select Id from Table2 join Table3;
SELECT id FROM dbo.Table1 INNER JOIN dbo.Table2 ON ...
EXCEPT
SELECT id FROM dbo.Table2 INNER JOIN dbo.Table3 ON ...;
try this one:
select Id from Table1 join Table2
union
select Id from Table2 join Table3

SQL UNION INNER JOIN

Im trying to select from 2 tables that have the same columns, but both tables have an inner join -
select e.ID,
c.FullName,
car.VIN,
car.Registration,
e.Telephone,
e.Mobile,
e.Email,
e.EstimateTotal,
e.LastUpdated,
e.LastUpdateBy from (select id from Estimates UNION ALL select id from PrivateEstimates) e
inner join Customers c on c.ID = e.CustomerID
inner join Cars car on car.ID = e.CarID
where e.Status = 0
The trouble is, it can't find e.CustomerID, e.CarID or e.Status on the inner join? Any ideas?
Your subquery
select id from Estimates
union all
select id from PrivateEstimates
returns only a single id column. Include necessary columns in the subquery if you want to use those columns in JOIN statements

SQL JOIN WITH WHERE

I am trying to join a table variable table and another table.
#ProcessTbl OrderDetail
Order ID
Status Order
Approved DateTime
Domain Status
OrderDetail table has multiple columns for same order. For example
ID Order DateTime Status
1 1 11-17-10 Recived
2 1 11-18-10 Processing
3 1 11-19-10 shipped
so what i want the join to do is take the order number from #processtbl(table variable)
and for max(id) get the datetime in this case the max id is 3
so my result should be
order status approved domain datetime
1 shipped true finance 11-19-10
SELECT t.order
,[od.DateTime]
,t.Status
,t.Domain
,t.Approved
FROM #ProcessTable t
JOIN OrderDetail od ON od.order= t.order
WHERE od.ID = (SELECT MAX(id) FROM orderdetail WHERE od.order = t.order )
ORDER BY od.[DateTime], Approved ASC
But I am still getting duplicate records , looks like it is joning both the tables.
How can I get distinct records?
select p.order, od.status, p.approved, p.domain, od.datetime
from #ProcessTable p
inner join (
select Order, max(ID) as MaxID
from OrderDetail
group by Order
) odm
inner join OrderDetail od on odm.Order = od.Order
and odm.MaxID = od.ID
Just a thought, have you tried to perform a SELECT DISTINCT?
WHERE od.ID = (SELECT MAX(id) FROM orderdetail WHERE od.order = t.order )
The od.order is not referencing the orderdetail table in the sub query but the instance outside.
Try something like: WHERE od.ID = (SELECT MAX(id) FROM orderdetail as od1 WHERE od1.order = t.order )

Resources