Using an Inner join select statement - sql

I am fairly new to SQL. I have created an inner join between 2 tables and further created some where clauses to pull out the appropriate data. As I understand it I have used an inner join to connect 2 tables. What I am trying to do now is connect my resultant select query to another table. How would I do this?
SELECT
t.[Type]
from [MITS].[dbo].[monster] t
inner join (
SELECT [MITS].[dbo].[BROKERTABLE].[BrokerID]
,[MITS].[dbo].[CustomerRates].[MPAN_ID]
,[MITS].[dbo].[BROKERTABLE].[Commission_Rate]
,[MITS].[dbo].[BROKERTABLE].[Rate_From]
,[MITS].[dbo].[BROKERTABLE].[Rate_To]
,[MITS].[dbo].[CustomerRates].[From_Date]
,[MITS].[dbo].[CustomerRates].[To_Date]
from [MITS].[dbo].[CustomerRates]
Inner Join [MITS].[dbo].[BROKERTABLE]
on [MITS].[dbo].[BROKERTABLE].[MPAN_ID] =
[MITS].[dbo].[CustomerRates].[MPAN_ID]
where
[MITS].[dbo].[CustomerRates].[To_Date] <=
[MITS].[dbo].[BROKERTABLE].[Rate_To]
and
convert(datetime,'01/11/2015',103)
between convert(datetime,[MITS].[dbo].[CustomerRates].[From_Date],103)
and convert(datetime,[MITS].[dbo].[CustomerRates].[To_Date],103)
) d on t.MITID = d.MPAT_ID

Add extra table into existing query: guess 1
select *
from atable a
inner join btable b on a.somecol = b.somecol
inner join extra_table t on a.somecol = t.somecol and b.somecol = t.somecol2
Add existing query to a table, method 1
select *
from extra_table t
inner join (
your existing query here
) d on t.somecol = d.somecol
Add existing query to a table, method 2
select *
from (
your existing query here
) d
inner join extra_table t on d.somecol = t.somecol

Related

Update data in temporary table with new records found with joins on other table

I have data in a temporary table and I need to update this with the new data found with other tables using joins. How can I change the second select to an update statement?
Can you please suggest how to do this?
Thank you
SELECT
sc.str_psn, sc.str_esn, sc.id_smartcard, sc.id_customer, st.str_statusdesc,
pax.str_title
INTO #temp
FROM Smartrack.dbo.Smartcard sc
INNER JOIN Smartrack.dbo.Customer pax on sc.id_customer = pax.id_customer
INNER JOIN SmarTrack.dbo.StatusType st ON sc.int1_cardstatus = st.int1_statustype
SELECT
t.str_psn , t.str_esn, t.id_smartcard, t.id_customer, t.str_statusdesc,
t.str_title, subpax.datAdded, tok.str_token_desc, subpax.ultTokenType
FROM #temp t
INNER JOIN (
SELECT p.id_Customer, u.id_TravelToken, u.ultTokenType, u.datAdded, u.ultTokenExpiry
FROM SmarTrack.dbo.Customer p
INNER JOIN SmarTrack.dbo.Smartcard s ON p.id_customer = s.id_customer
INNER JOIN SmartrackInterface.dbo.vwUltimateCardDetails u ON s.id_smartcard = u.id_smartcard
WHERE s.id_replacement_smartcard IS NULL
) subpax ON t.id_customer = subpax.id_CUstomer
INNER JOIN SmarTrack.dbo.TravelToken tt ON subpax.id_TravelToken = tt.id_traveltoken
INNER JOIN SmarTrack.dbo.TokenType tok on subpax.ultTokenType = tok.int2_tokentype
Your question is similar to this: Update records in table from CTE
Your can try the following method
with cte as(
SELECT
t.str_psn , t.str_esn, t.id_smartcard, t.id_customer, t.str_statusdesc,
t.str_title, subpax.datAdded, tok.str_token_desc, subpax.ultTokenType
FROM #temp t
INNER JOIN (
SELECT p.id_Customer, u.id_TravelToken, u.ultTokenType, u.datAdded, u.ultTokenExpiry
FROM SmarTrack.dbo.Customer p
INNER JOIN SmarTrack.dbo.Smartcard s ON p.id_customer = s.id_customer
INNER JOIN SmartrackInterface.dbo.vwUltimateCardDetails u ON s.id_smartcard = u.id_smartcard
WHERE s.id_replacement_smartcard IS NULL
) subpax ON t.id_customer = subpax.id_CUstomer
INNER JOIN SmarTrack.dbo.TravelToken tt ON subpax.id_TravelToken = tt.id_traveltoken
INNER JOIN SmarTrack.dbo.TokenType tok on subpax.ultTokenType = tok.int2_tokentype
)
Update #temp
Set #temp.id_customer in (Select distinct id_customer From cte)

How to optimize long running cte

I have one query that is taking 10 minute and giving me 6852104 records. How can I optimize it? I have added execution plan as well.
My query is like this:
WITH CTE (columns name
)
AS (
SELECT columns
FROM #tempTable b WITH (NOLOCK)
INNER JOIN physicaltable1 A ON A.ParentInvoiceItemId = b.InvoiceItemId
INNER JOIN physicaltable2 c ON c.LinkedInvoiceItemId = a.LinkedInvoiceItemId
AND c.HospitalId = B.Hospital_Id
UNION ALL
SELECT columns
FROM CTE LIP
JOIN physicaltable1 LIC ON LIP.ChildInvoiceItemId = LIC.ParentInvoiceItemId
INNER JOIN physicaltable12 LIH ON LIH.LinkedInvoiceItemId = LIC.LinkedInvoiceItemId
AND LIH.HospitalId = LIP.HospitalId
WHERE LIP.[Level] < 3
)
SELECT *
INTO #newtemptable
FROM CTE;

Join on TOP 1 from subquery while referencing outer tables

I am starting with this query, which works fine:
SELECT
C.ContactSys
, ... a bunch of other rows...
FROM Users U
INNER JOIN Contacts C ON U.ContactSys = C.ContactSys
LEFT JOIN UserWatchList UW ON U.UserSys = UW.UserSys
LEFT JOIN Accounts A ON C.AccountSys = A.AccountSys
WHERE
C.OrganizationSys = 1012
AND U.UserTypeSys = 2
AND C.FirstName = 'steve'
Now, I've been given this requirement:
For every visitor returned by the Visitor Search, take ContactSys, get the most recent entry in the GuestLog table for that contact, then return the columns ABC and XYZ from the GuestLog table.
I'm having trouble with that. I need something like this (I think)...
SELECT
C.ContactSys
, GL.ABC
, GL.XYZ
, ... a bunch of other rows...
FROM Users U
INNER JOIN Contacts C ON U.ContactSys = C.ContactSys
LEFT JOIN UserWatchList UW ON U.UserSys = UW.UserSys
LEFT JOIN Accounts A ON C.AccountSys = A.AccountSys
LEFT JOIN (SELECT TOP 1 * FROM GuestLog GU WHERE GU.ContactSys = ????? ORDER BY GuestLogSys DESC) GL ON GL.ContactSys = C.ContactSys
WHERE
C.OrganizationSys = 1012
AND U.UserTypeSys = 2
AND C.FirstName = 'steve'
Only that's not it because that subquery on the JOIN doesn't know anything about the outer tables.
I've been looking at these posts and their answers, but I'm having a hard time translating them to my needs:
SQL: Turn a subquery into a join: How to refer to outside table in nested join where clause?
Reference to outer query in subquery JOIN
Referencing outer query in subquery
Referencing outer query's tables in a subquery
If that is the logic you want, you can use OUTER APPLY:
SELECT C.ContactSys, GL.ABC, GL.XYZ,
... a bunch of other columns ...
FROM Users U JOIN
Contacts C
ON U.ContactSys = C.ContactSys LEFT JOIN
UserWatchList UW
ON U.UserSys = UW.UserSys LEFT JOIN
Accounts A
ON C.AccountSys = A.AccountSys OUTER APPLY
(SELECT TOP 1 gl.*
FROM GuestLog gl
WHERE gl.ContactSys = C.ContactSys
ORDER BY gl.GuestLogSys DESC
) GL
WHERE C.OrganizationSys = 1012 AND
U.UserTypeSys = 2 AND
C.FirstName = 'steve'

Sum record data into one

I have this query which returns qty in each of my branch. now the branch has two WH_subType as you see in the attached diagram i have attached. I want to sum the 2 subtype and show its available qty. how can i do it.
my select query is like this
SELECT
dbo.WarehouseType.name AS Section,
dbo.WarehouseSubType.name AS WH_Type,
dbo.WarehouseSubType1.name AS WH_SubType,
dbo.Branch.name AS Branch,
(dbo.WarehouseProductQuantity.actualQuantity - dbo.WarehouseProductQuantity.reservedQuantity) AS AvailQty,
dbo.WarehouseProductQuantity.tafsilId AS Tafsil,
dbo.Tafsil.description AS Product_Name
FROM
dbo.WarehouseSubType
INNER JOIN
dbo.WarehouseType
ON
(
dbo.WarehouseSubType.warehouseTypeId = dbo.WarehouseType.id)
INNER JOIN
dbo.WarehouseSubType1
ON
(
dbo.WarehouseSubType.id = dbo.WarehouseSubType1.warehouseSubTypeId)
INNER JOIN
dbo.Warehouse
ON
(
dbo.WarehouseSubType1.id = dbo.Warehouse.warehouseSubType1Id)
INNER JOIN
dbo.Branch
ON
(
dbo.Warehouse.branchId = dbo.Branch.id)
INNER JOIN
dbo.WarehouseProductQuantity
ON
(
dbo.Warehouse.id = dbo.WarehouseProductQuantity.warehouseId)
INNER JOIN
dbo.TafsilLink
ON
(
dbo.WarehouseProductQuantity.tafsilId = dbo.TafsilLink.sourceId)
INNER JOIN
dbo.Tafsil
ON
(
dbo.TafsilLink.targetId = dbo.Tafsil.id)
INNER JOIN
dbo.FinishProduct
ON
(
dbo.Tafsil.id = dbo.FinishProduct.tafsilId)
INNER JOIN
dbo.Supplier
ON
(
dbo.FinishProduct.supplierId = dbo.Supplier.tafsilId)
WHERE
WarehouseSubType1.warehouseSubTypeId IN (1,4)
group by dbo.WarehouseProductQuantity.tafsilId
Have you tried a group by
SELECT SubType, SUM(qty) AS QtySum
GROUP BY SubType
Every grouped by column should be in your select. Note: for every column you group by it further sub divides the data
Update based on OP comment:
If you want other columns you need to do something like
SELECT s.WH_SubType,s.AvailQty, t.other_cols
from
(SELECT
dbo.WarehouseSubType1.name AS WH_SubType,
sum(dbo.WarehouseProductQuantity.actualQuantity - dbo.WarehouseProductQuantity.reservedQuantity) AS AvailQty
FROM
table
GROUP BY
dbo.WarehouseSubType1.name) s
left join table t on t.dbo.WarehouseSubType1.name = s.WH_SubType;
For reference see this question: How do I use "group by" with three columns of data?
UPDATE 2:
SELECT
dbo.WarehouseType.name AS Section,
dbo.WarehouseSubType.name AS WH_Type,
dbo.WarehouseSubType1.name AS WH_SubType,
dbo.Branch.name AS Branch,
SumTable.AvailQty,
SumTable.Tafsil,
dbo.Tafsil.description AS Product_Name
FROM
dbo.WarehouseSubType
INNER JOIN
dbo.WarehouseType
ON
(
dbo.WarehouseSubType.warehouseTypeId = dbo.WarehouseType.id)
INNER JOIN
dbo.WarehouseSubType1
ON
(
dbo.WarehouseSubType.id = dbo.WarehouseSubType1.warehouseSubTypeId)
INNER JOIN
dbo.Warehouse
ON
(
dbo.WarehouseSubType1.id = dbo.Warehouse.warehouseSubType1Id)
INNER JOIN
dbo.Branch
ON
(
dbo.Warehouse.branchId = dbo.Branch.id)
INNER JOIN
dbo.WarehouseProductQuantity
ON
(
dbo.Warehouse.id = dbo.WarehouseProductQuantity.warehouseId)
INNER JOIN
dbo.TafsilLink
ON
(
dbo.WarehouseProductQuantity.tafsilId = dbo.TafsilLink.sourceId)
INNER JOIN
dbo.Tafsil
ON
(
dbo.TafsilLink.targetId = dbo.Tafsil.id)
INNER JOIN
dbo.FinishProduct
ON
(
dbo.Tafsil.id = dbo.FinishProduct.tafsilId)
LEFT JOIN (SELECT
sum(dbo.WarehouseProductQuantity.actualQuantity - dbo.WarehouseProductQuantity.reservedQuantity) AS AvailQty,
dbo.WarehouseProductQuantity.tafsilId AS Tafsil
FROM
dbo.WarehouseProductQuantity
group by dbo.WarehouseProductQuantity.tafsilId) SumTable on dbo.Tafsil.id = SumTable.Tafsil
WHERE
WarehouseSubType1.warehouseSubTypeId IN (1,4)
You need to do something like
SELECT SUM(AvailQty), ... FROM ... WHERE ... GROUP BY WH_SubType
http://www.w3schools.com/sql/sql_func_sum.asp
http://www.w3schools.com/sql/sql_groupby.asp

selecting the max values based on a count

How can i retrieve the max of each ValueCount based on the firmid. I need the data to be output like so.
My code is below
SELECT
F.FirmID,
F.Name,
DL.ValueId,
DL.ValueName,
count(DL.ValueName) AS ValueCount
FROM
dbo.Jobs AS J
INNER JOIN DimensionValues AS DV ON
DV.CrossRef = J.JobId
INNER JOIN dbo.DimensionLists AS DL ON
DV.ValueId = DL.ValueId
INNER JOIN Firms AS F ON
F.FirmId = J.ClientFirmId
WHERE
DL.DimensionId = 4
GROUP BY
F.FirmID,
F.Name,
DL.ValueName,
DL.ValueId
this produces something like
firmid | value | count
1 1 5
1 2 10
2 3 1
2 1 6
i need to return back the records with 10 and 6.
EDIT : SQL 2005 answer deleted.
Then you could push your results into a temporary table (or table variable) and do something like this...
SELECT
*
FROM
TempTable
WHERE
ValueCount = (SELECT MAX(ValueCount) FROM TempTable AS Lookup WHERE FirmID = TempTable.FirmID)
Or...
SELECT
*
FROM
TempTable
INNER JOIN
(SELECT FirmID, MAX(ValueCount) AS ValueCount FROM TempTable GROUP BY FirmID) AS lookup
ON lookup.FirmID = TempTable.FirmID
AND lookup.ValueCount = TempTable.ValueCount
These will give multiple records if any ValueCount is tied with another for the same FirmID. As such, you could try this...
SELECT
*
FROM
TempTable
WHERE
value = (
SELECT TOP 1
value
FROM
TempTable as lookup
WHERE
FirmID = TempTable.FirmID
ORDER BY
ValueCount DESC
)
For this problem you need to produce the result set of the query in order to determine the Max ValueCount, then you need to do the query again to pull just the records with Max ValueCount. You can do this many way, like repeating the main query as subqueries, and in SQL Server 2005/2008 by using a CTE. I think using the subqueries gets a little messy and would prefer the CTE, but for SQL Server 2000 you don't have that as an option. So, I've used a temp table instead of a CTE. I run it once to get the MaxValueCount and save that into a temp table, then run the query again and join against the temp table to get just the record with MaxValueCount.
create table #tempMax
(
FirmID int,
MaxValueCount int
)
insert #tempMax
SELECT t.FirmID, MAX(t.ValueCount) AS MaxValueCount
FROM (
SELECT F.FirmID, F.Name, DL.ValueId, DL.ValueName
, count(DL.ValueName) AS ValueCount
FROM dbo.Jobs AS J
INNER JOIN DimensionValues AS DV ON DV.CrossRef = J.JobId
INNER JOIN dbo.DimensionLists AS DL ON DV.ValueId = DL.ValueId
INNER JOIN Firms AS F ON F.FirmId = J.ClientFirmId
WHERE DL.DimensionId = 4
GROUP BY F.FirmID, F.Name, DL.ValueName, DL.ValueId) t
SELECT t.FirmID, t.Name, t.ValueID, t.ValueName, t.ValueCount
FROM (
SELECT F.FirmID, F.Name, DL.ValueId, DL.ValueName
, count(DL.ValueName) AS ValueCount
FROM dbo.Jobs AS J
INNER JOIN DimensionValues AS DV ON DV.CrossRef = J.JobId
INNER JOIN dbo.DimensionLists AS DL ON DV.ValueId = DL.ValueId
INNER JOIN Firms AS F ON F.FirmId = J.ClientFirmId
WHERE DL.DimensionId = 4
GROUP BY F.FirmID, F.Name, DL.ValueName, DL.ValueId) t
INNER JOIN #tempMax m ON t.FirmID = m.FirmID and t.ValueCount = m.MaxValueCount
DROP TABLE #tempMax
You should be able to use a derived table for this:
SELECT F.FirmID,
F.Name,
DL.ValueId,
DL.ValueName,
T.ValueCount
FROM Jobs J
INNER JOIN DimensionValues DV
ON DV.Crossref = J.JobID
INNER JOIN DimensionList DL
ON DV.ValueID = DL.ValueID
INNER JOIN Firms F
ON F.FirmID = J.ClientFirmID
--derived table
INNER JOIN (SELECT FirmID, MAX(ValueName) ValueCount FROM DimensionList GROUP BY FirmID) T
ON T.FirmID = F.FirmID
WHERE DL.DimensionId = 4
TBL1 and TBL2 is your query:
SELECT *
FROM TBL1
WHERE
TBL1.ValueCount = (SELECT MAX(TBL2.ValueCount) FROM TBL2 WHERE TBL2.FIRMID = TBL1.FIRMID)