TeDeSm
asked on
SQL - Subquery Syntax
I have a query that returns a number of rows with a given set of criteria. I require to subquery one of the tables with a different criteria value to return 1 extra column. I am having trouble getting the syntax correct.
The original query is:
I need to return [Order Number] from:
subqueryFloyd.dbo.Transact ionHistory .SecondRef erence AS [Order Number]
WHERE subqueryFloyd.dbo.Transact ionHistory .Transacti onTypeID = 13
AND subqueryFloyd.dbo.Transact ionHistory .Reference = mainqueryFloyd.dbo.Transac tionHistor y.Referenc e
The original query is:
SELECT TOP (100) PERCENT Floyd.dbo.SLCustomerAccount.CustomerAccountNumber AS [Acct Number],
Floyd.dbo.SLCustomerAccount.CustomerAccountName AS [Acct Name], Floyd.dbo.TransactionHistory.TransactionDate AS [Invoice Date],
Floyd.dbo.TransactionHistory.SecondReference AS [Invoice Number], Floyd.dbo.StockItem.Code AS [Item Number], Floyd.dbo.StockItem.Name,
Floyd.dbo.StockItem.Description, Floyd.dbo.TransactionHistory.Quantity, Floyd.dbo.TransactionHistory.Reference AS [Floyd Order],
Floyd.dbo.TransactionHistory.UnitIssuePrice AS [Item Price], Floyd.dbo.TransactionHistory.UnitDiscountValue AS Discount,
Floyd.dbo.TransactionHistory.IssueValue AS [Line Total]
FROM Floyd.dbo.StockItem INNER JOIN
Floyd.dbo.TransactionHistory ON Floyd.dbo.StockItem.ItemID = Floyd.dbo.TransactionHistory.ItemID INNER JOIN
Floyd.dbo.SLCustomerAccount ON Floyd.dbo.TransactionHistory.SourceAreaReference = Floyd.dbo.SLCustomerAccount.CustomerAccountNumber
WHERE (Floyd.dbo.TransactionHistory.TransactionDate >= CONVERT(DATETIME, '2012-06-01 00:00:00', 102)) AND
(Floyd.dbo.TransactionHistory.TransactionDate <= CONVERT(DATETIME, '2012-08-31 00:00:00', 102)) AND
(Floyd.dbo.SLCustomerAccount.CustomerAccountNumber = '118') AND (Floyd.dbo.TransactionHistory.TransactionTypeID = 15)
ORDER BY [Invoice Date]
I need to return [Order Number] from:
subqueryFloyd.dbo.Transact
WHERE subqueryFloyd.dbo.Transact
AND subqueryFloyd.dbo.Transact
ASKER
Thanks lwadwell. I get duplicates trying your method. My main query outputs 47 rows without any changes, 157 if I add in TransactionHistory again filtered on TransactionTypeID=13.
As long as your subquery returns a single row per matched join, try adding it as another "field" you are selecting. You should be able to join from your query into a sub select like this without any issues.
SELECT TOP (100) PERCENT Floyd.dbo.SLCustomerAccoun t.Customer AccountNum ber AS [Acct Number],
Floyd.dbo.SLCustomerAccoun t.Customer AccountNam e AS [Acct Name],
Floyd.dbo.TransactionHisto ry.Transac tionDate AS [Invoice Date],
Floyd.dbo.TransactionHisto ry.SecondR eference AS [Invoice Number],
Floyd.dbo.StockItem.Code AS [Item Number], Floyd.dbo.StockItem.Name,
Floyd.dbo.StockItem.Descri ption, Floyd.dbo.TransactionHisto ry.Quantit y,
Floyd.dbo.TransactionHisto ry.Referen ce AS [Floyd Order],
Floyd.dbo.TransactionHisto ry.UnitIss uePrice AS [Item Price],
Floyd.dbo.TransactionHisto ry.UnitDis countValue AS Discount,
Floyd.dbo.TransactionHisto ry.IssueVa lue AS [Line Total],
( select sub.SecondReference
FROM Floyd.dbo.TransactionHisto ry sub
WHERE sub.TransactionTypeID = 13
AND sub.Reference = Floyd.dbo.TransactionHisto ry.Referen ce) as Order_Number
FROM Floyd.dbo.StockItem INNER JOIN
Floyd.dbo.TransactionHisto ry ON Floyd.dbo.StockItem.ItemID = Floyd.dbo.TransactionHisto ry.ItemID INNER JOIN
Floyd.dbo.SLCustomerAccoun t ON Floyd.dbo.TransactionHisto ry.SourceA reaReferen ce = Floyd.dbo.SLCustomerAccoun t.Customer AccountNum ber
WHERE (Floyd.dbo.TransactionHist ory.Transa ctionDate >= CONVERT(DATETIME, '2012-06-01 00:00:00', 102)) AND
(Floyd.dbo.TransactionHist ory.Transa ctionDate <= CONVERT(DATETIME, '2012-08-31 00:00:00', 102)) AND
(Floyd.dbo.SLCustomerAccou nt.Custome rAccountNu mber = '118') AND (Floyd.dbo.TransactionHist ory.Transa ctionTypeI D = 15)
ORDER BY [Invoice Date]
SELECT TOP (100) PERCENT Floyd.dbo.SLCustomerAccoun
Floyd.dbo.SLCustomerAccoun
Floyd.dbo.TransactionHisto
Floyd.dbo.TransactionHisto
Floyd.dbo.StockItem.Code AS [Item Number], Floyd.dbo.StockItem.Name,
Floyd.dbo.StockItem.Descri
Floyd.dbo.TransactionHisto
Floyd.dbo.TransactionHisto
Floyd.dbo.TransactionHisto
Floyd.dbo.TransactionHisto
( select sub.SecondReference
FROM Floyd.dbo.TransactionHisto
WHERE sub.TransactionTypeID = 13
AND sub.Reference = Floyd.dbo.TransactionHisto
FROM Floyd.dbo.StockItem INNER JOIN
Floyd.dbo.TransactionHisto
Floyd.dbo.SLCustomerAccoun
WHERE (Floyd.dbo.TransactionHist
(Floyd.dbo.TransactionHist
(Floyd.dbo.SLCustomerAccou
ORDER BY [Invoice Date]
Do you need to apply the date range check again too? i.e.
SELECT Floyd.dbo.SLCustomerAccount.CustomerAccountNumber AS [Acct Number],
Floyd.dbo.SLCustomerAccount.CustomerAccountName AS [Acct Name], Floyd.dbo.TransactionHistory.TransactionDate AS [Invoice Date],
Floyd.dbo.TransactionHistory.SecondReference AS [Invoice Number], Floyd.dbo.StockItem.Code AS [Item Number], Floyd.dbo.StockItem.Name,
Floyd.dbo.StockItem.Description, Floyd.dbo.TransactionHistory.Quantity, Floyd.dbo.TransactionHistory.Reference AS [Floyd Order],
Floyd.dbo.TransactionHistory.UnitIssuePrice AS [Item Price], Floyd.dbo.TransactionHistory.UnitDiscountValue AS Discount,
Floyd.dbo.TransactionHistory.IssueValue AS [Line Total]
SecondReference.SecondReference AS [Order Number]
FROM Floyd.dbo.StockItem
INNER JOIN Floyd.dbo.TransactionHistory ON Floyd.dbo.StockItem.ItemID = Floyd.dbo.TransactionHistory.ItemID
INNER JOIN Floyd.dbo.SLCustomerAccount ON Floyd.dbo.TransactionHistory.SourceAreaReference = Floyd.dbo.SLCustomerAccount.CustomerAccountNumber
INNER JOIN Floyd.dbo.TransactionHistory SecondReference ON SecondReference.TransactionTypeID = 13 AND SecondReference.Reference = Floyd.dbo.TransactionHistory.Reference
WHERE (Floyd.dbo.TransactionHistory.TransactionDate >= CONVERT(DATETIME, '2012-06-01 00:00:00', 102))
AND (Floyd.dbo.TransactionHistory.TransactionDate <= CONVERT(DATETIME, '2012-08-31 00:00:00', 102))
AND (SecondReference.TransactionDate >= CONVERT(DATETIME, '2012-06-01 00:00:00', 102))
AND (SecondReference.TransactionDate <= CONVERT(DATETIME, '2012-08-31 00:00:00', 102))
AND (Floyd.dbo.SLCustomerAccount.CustomerAccountNumber = '118') AND (Floyd.dbo.TransactionHistory.TransactionTypeID = 15)
ORDER BY [Invoice Date]
ASKER
I think the problem is the subquery could return more than one row. Perhaps a better way would be to run as part of a stored procedure which would have been my next step. Within that sp I think the subquery could be run with DISTINCT to give single rows per Floyd.dbo.TransactionHisto ry.Referen ce, and then matched with the main query in the final output.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
All three examples work as the single value returned is unique to each instance of the linked column .Reference. Thanks for the help in getting the syntax correct.
DISTINCT is my preferred method as in the SQL below:
SELECT TOP (100) PERCENT Floyd.dbo.SLCustomerAccoun t.Customer AccountNum ber AS [Acct Number],
Floyd.dbo.SLCustomerAccoun t.Customer AccountNam e AS [Acct Name], Floyd.dbo.TransactionHisto ry.Transac tionDate AS [Invoice Date],
Floyd.dbo.TransactionHisto ry.SecondR eference AS [Invoice Number],
(SELECT DISTINCT SecondReference
FROM Floyd.dbo.TransactionHisto ry AS sub
WHERE (TransactionTypeID = 12) AND (Reference = Floyd.dbo.TransactionHisto ry.Referen ce)) AS Order_Number, Floyd.dbo.StockItem.Code AS [Item Number],
Floyd.dbo.StockItem.Name, Floyd.dbo.StockItem.Descri ption, Floyd.dbo.TransactionHisto ry.Quantit y, Floyd.dbo.TransactionHisto ry.Referen ce AS [Floyd Order],
Floyd.dbo.TransactionHisto ry.UnitIss uePrice AS [Item Price], Floyd.dbo.TransactionHisto ry.UnitDis countValue AS Discount,
Floyd.dbo.TransactionHisto ry.IssueVa lue AS [Line Total]
FROM Floyd.dbo.StockItem INNER JOIN
Floyd.dbo.TransactionHisto ry ON Floyd.dbo.StockItem.ItemID = Floyd.dbo.TransactionHisto ry.ItemID INNER JOIN
Floyd.dbo.SLCustomerAccoun t ON Floyd.dbo.TransactionHisto ry.SourceA reaReferen ce = Floyd.dbo.SLCustomerAccoun t.Customer AccountNum ber
WHERE (Floyd.dbo.TransactionHist ory.Transa ctionDate >= CONVERT(DATETIME, '2012-06-01 00:00:00', 102)) AND
(Floyd.dbo.TransactionHist ory.Transa ctionDate <= CONVERT(DATETIME, '2012-08-31 00:00:00', 102)) AND
(Floyd.dbo.SLCustomerAccou nt.Custome rAccountNu mber = '118') AND (Floyd.dbo.TransactionHist ory.Transa ctionTypeI D = 15)
ORDER BY [Invoice Date]
DISTINCT is my preferred method as in the SQL below:
SELECT TOP (100) PERCENT Floyd.dbo.SLCustomerAccoun
Floyd.dbo.SLCustomerAccoun
Floyd.dbo.TransactionHisto
(SELECT DISTINCT SecondReference
FROM Floyd.dbo.TransactionHisto
WHERE (TransactionTypeID = 12) AND (Reference = Floyd.dbo.TransactionHisto
Floyd.dbo.StockItem.Name, Floyd.dbo.StockItem.Descri
Floyd.dbo.TransactionHisto
Floyd.dbo.TransactionHisto
FROM Floyd.dbo.StockItem INNER JOIN
Floyd.dbo.TransactionHisto
Floyd.dbo.SLCustomerAccoun
WHERE (Floyd.dbo.TransactionHist
(Floyd.dbo.TransactionHist
(Floyd.dbo.SLCustomerAccou
ORDER BY [Invoice Date]
e.g.
Open in new window