Combine two subqueries to main query in SQL - sql-server

I am new to SQL and need assistance to combine (JOIN) two subqueries with a main query in SQL. Here is what I have. *Each query works independent of another. The end result would be that I would retrieve the # of accommodations for each resort, retrieve the lowest cost of all accommodations for each resort, and join those results to the list of resort types and resorts.
DB Schema
Table 1 - Resort -
resort_id (PK)
resort_type_id (FK)
name
Table 2 - Resort_type -
resort_type_id (PK)
resort_type
Table 3 - Accommodations -
accommodations_id (PK)
resort_id (FK)
description
cost_per_night
Query
SELECT Resort.name, Resort_type, Acc.Accommodations, Low.min_price
FROM
(SELECT resort.name AS resort_name, Resort_type.resort_type
FROM Resort
INNER JOIN Resort_type
ON Resort.resort_type_id = Resort_type.resort_type_id
(SELECT resort_id, Count(resort_id) AS Accommodations
FROM Accommodations
GROUP BY resort_id) AS Acc
(SELECT resort_id, Min(cost_per_night) AS min_price
FROM Accommodations
GROUP BY resort_id) AS Low
Any guidance would be greatly appreciated. I am having a difficult time visualizing how this should come together.

The query below lists each resort and its type along with the number of accommodations and the lowest cost per night.
select
r.name,
t.resort_type as type,
count(a.accommodations_id) as accommodations,
min(cost_per_night) as lowestcost
from resort r
inner join resort_type t
on t.resort_type_id = r.resort_type_id
left join accommodations a
on a.resort_id = r.resort_id
group by r.name, t.resort_type
Example: http://sqlfiddle.com/#!9/fc089/6

Is this what you're looking for:
SELECT
r.name,
rt.resort_type,
t.no_of_accommodations,
t.min_price
FROM Resort r
INNER JOIN Resort_Type rt
ON rt.resort_type_id = r.resort_type_id
LEFT JOIN(
SELECT
COUNT(*) AS no_of_accommodations,
MIN(cost_per_night) AS min_price
FROM Accommodations
GROUP BY resort_id
)t
ON t.resort_id = r.resort_id

Related

Combine multiple left joins in 1 query

I have two queries that I would like to combine. One query is left joining columns in the same table, the other query is left joining columns from two different tables. Both queries have the same table, just unsure how to properly set up the query.
1st Query:
SELECT BIZ_GROUP,
ORDER_ID,
STATION,
A.TC_DATE,
WANT_DATE,
TIME_SLOT,
JOB_CODE,
[ADDRESS],
CITY,
A.TECH_ID,
A.PREMISE,
ISNULL(B.LAST_ARRIVED, A.LAST_ARRIVE) AS ARRIVED,
ORDER_CLOSED,
COMP_STATUS,
WORK_STATUS,
REMARKS,
CORRECTION
FROM MET_timecommit A
LEFT JOIN(SELECT premise,
TC_DATE,
TECH_ID,
MIN(last_arrive) AS LAST_ARRIVED
FROM MET_timecommit
WHERE PREMISE IS NOT NULL
GROUP BY premise,
TC_DATE,
TECH_ID) B ON B.TC_DATE = A.TC_DATE
AND B.PREMISE = A.PREMISE
2nd query:
SELECT *
FROM MET_timecommit
LEFT JOIN (SELECT ORDER_ID,
created,
host_creation,
went_to
FROM workload
WHERE went_to >= getdate()-365) C ON C.went_to=MET_timecommit.TC_DATE
AND C.order_id=MET_timecommit.order_id
Evidently I am not used to this forum. You all don't have to be so rude. TDP was able to help me out based on what I provided. All other comments were unnecessary.
This should bring back the rows for both tables B and C for each row of table A:
SELECT A.BIZ_GROUP,
A.ORDER_ID,
A.STATION,
A.TC_DATE,
A.WANT_DATE,
A.TIME_SLOT,
A.JOB_CODE,
A.[ADDRESS],
A.CITY,
A.TECH_ID,
A.PREMISE,
ISNULL(B.LAST_ARRIVED, A.LAST_ARRIVE) AS ARRIVED,
A.ORDER_CLOSED,
A.COMP_STATUS,
A.WORK_STATUS,
A.REMARKS,
A.CORRECTION,
C.*
FROM MET_timecommit A
LEFT JOIN(SELECT premise,
TC_DATE,
TECH_ID,
MIN(last_arrive) AS LAST_ARRIVED
FROM MET_timecommit
WHERE PREMISE IS NOT NULL
GROUP BY premise,
TC_DATE,
TECH_ID) B ON B.TC_DATE = A.TC_DATE
AND B.PREMISE = A.PREMISE
LEFT JOIN (SELECT ORDER_ID,
created,
host_creation,
went_to
FROM workload
WHERE went_to >= getdate()-365) C ON C.went_to=A.MET_timecommit.TC_DATE
AND C.order_id=A.MET_timecommit.order_id

Why do I have duplicate records in my JOIN

I am retrieving data from table ProductionReportMetrics where I have column NetRate_QuoteID. Then to that result set I need to get Description column.
And in order to get a Description column, I need to join 3 tables:
NetRate_Quote_Insur_Quote
NetRate_Quote_Insur_Quote_Locat
NetRate_Quote_Insur_Quote_Locat_Liabi
But after that my premium is completely off.
What am I doing wrong here?
SELECT QLL.Description,
QLL.ClassCode,
prm.NetRate_QuoteID,
QL.LocationID,
ISNULL(SUM(premium),0) AS NetWrittenPremium,
MONTH(prm.EffectiveDate) AS EffMonth
FROM ProductionReportMetrics prm
LEFT JOIN NetRate_Quote_Insur_Quote Q
ON prm.NetRate_QuoteID = Q.QuoteID
INNER JOIN NetRate_Quote_Insur_Quote_Locat QL
ON Q.QuoteID = QL.QuoteID
INNER JOIN NetRate_Quote_Insur_Quote_Locat_Liabi QLL
ON QL.LocationID = QLL.LocationID
WHERE YEAR(prm.EffectiveDate) = 2016 AND
CompanyLine = 'Ironshore Insurance Company'
GROUP BY MONTH(prm.EffectiveDate),
QLL.Description,
QLL.ClassCode,
prm.NetRate_QuoteID,
QL.LocationID
I think the problem in this table:
What Am I missing in this Query?
select
ClassCode,
QLL.Description,
sum(Premium)
from ProductionReportMetrics prm
LEFT JOIN NetRate_Quote_Insur_Quote Q ON prm.NetRate_QuoteID = Q.QuoteID
LEFT JOIN NetRate_Quote_Insur_Quote_Locat QL ON Q.QuoteID = QL.QuoteID
LEFT JOIN
(SELECT * FROM NetRate_Quote_Insur_Quote_Locat_Liabi nqI
JOIN ( SELECT LocationID, MAX(ClassCode)
FROM NetRate_Quote_Insur_Quote_Locat_Liabi GROUP BY LocationID ) nqA
ON nqA.LocationID = nqI.LocationID ) QLL ON QLL.LocationID = QL.LocationID
where Year(prm.EffectiveDate) = 2016 AND CompanyLine = 'Ironshore Insurance Company'
GROUP BY Q.QuoteID,QL.QuoteID,QL.LocationID
Now it says
Msg 8156, Level 16, State 1, Line 14
The column 'LocationID' was specified multiple times for 'QLL'.
It looks like DVT basically hit on the answer. The only reason you would get different amounts(i.e. duplicated rows) as a result of a join is that one of the joined tables is not a 1:1 relationship with the primary table.
I would suggest you do a quick check against those tables, looking for table counts.
--this should be your baseline count
SELECT COUNT(*)
FROM ProductionReportMetrics
GROUP BY MONTH(prm.EffectiveDate),
prm.NetRate_QuoteID
--this will be a check against the first joined table.
SELECT COUNT(*)
FROM NetRate_Quote_Insur_Quote Q
WHERE QuoteID IN
(SELECT NetRate_QuoteID
FROM ProductionReportMetrics
GROUP BY MONTH(prm.EffectiveDate),
prm.NetRate_QuoteID)
Basically you will want to do a similar check against each of your joined tables. If any of the joined tables are part of the grouping statement, make sure they are also in the grouping of the count check statement. Also make sure to alter the WHERE clause of the check count statement to use the join clause columns you were using.
Once you find a table that returns the incorrect number of rows, you will have your answer as to what table is causing the problem. Then you will just have to decide how to limit that table down to distinct rows(some type of aggregation).
This advice is really just to show you how to QA this particular query. Break it up into the smallest possible parts. In this case, we know that it is a join that is causing the problem, so take it one join at a time until you find the offender.

SQL: Select a column independent of where clause

SELECT TOP 1000 p.Title,p.Distributor, SUM(r.SalesVolume) AS VolumeOfSales,
CAST(SUM(r.CustomerPrice*r.SalesVolume) as decimal (18,0)) AS ValueOfSales,
CAST (AVG(r.CustomerPrice) as decimal (18,1)) AS AvgPrice,
p.MS_ContentType AS category ,Min(c.WeekId) AS ReleaseWeek
from Product p
INNER JOIN RawData r
ON p.ProductId = r.ProductId
INNER JOIN Calendar c
ON r.DayId = c.DayId
WHERE c.WeekId BETWEEN ('20145231') AND ('20145252')
AND p.Distributor IN ('WARNER', 'TF1', 'GAUMONT')
AND p.VODEST IN ('VOD', 'EST')
AND p.ContentFlavor IN ('SD', 'HD', 'NC')
AND p.MS_ExternalID1 IN ('ADVENTURE/ACTION', 'ANIMATION/FAMILY', 'COMEDY')
AND p.MS_ContentType IN ('FILM', 'TV', 'OTHERS')
AND r.CountryId = 1
GROUP BY p.Title,p.Distributor,p.MS_ContentType
ORDER BY VolumeOfSales DESC, ValueOfSales DESC
I want to madify the above query so that only the column ReleaseWeek is independent of the where clause WHERE c.WeekId BETWEEN ('20145231') AND ('20145252')
The result that I dervive looks like:
`Title Distributor VolumeOfSales ValueOfSales AvgPrice category ReleaseWeek
Divergente M6SND 94038 450095 4.0 Film 20145233`
However what I really want is the ReleaseWeek to be the first value in the column c.WeekId corresponding to that Titlein the database and not the first one between ('20145231') AND ('20145252') What is the best way to modify it? Any leads would be greatful.

LEFT JOIN gets heavy as the number of records in the second table increases

I am trying to run a SELECT query using LEFT JOIN. I get a COUNT on my second table ( the table on the right side of LEFT JOIN ). This process becomes slightly heavy as the number of records on the second table goes up. My first and second table have a one-to-many relationship. The second table's CampaignId column is a foreign key to the first table's Id. This is a simplified version of my query:
SELECT a.[Id]
,a.CampaignId
,a.[Inserted] AS 'Date'
,COUNT(b.Id) AS 'Received'
FROM [CampaignRun] AS a
LEFT JOIN [CampaignRecipient] AS b
ON a.Id = b.CampaignRunId
GROUP BY
a.[Id], a.CampaignId,a.[Inserted]
HAVING
a.CampaignId = 637
ORDER BY
a.[Inserted] DESC
The number 637 is an example for one the records only.
Is there a way to make this query run faster?
Use a sub-select to calculate Received:
SELECT a.[Id]
,a.CampaignId
,a.[Inserted] AS 'Date'
, (SELECT COUNT(*) FROM [CampaignRecipient] AS b
WHERE a.Id = b.CampaignRunId ) AS 'Received'
FROM [CampaignRun] AS a
WHERE a.CampaignId = 637
ORDER BY a.[Inserted] DESC
You have unneed HAVING clause here, which you can move to WHERE clause
SELECT a.[Id]
,a.CampaignId
,a.[Inserted] AS 'Date'
,COUNT(b.Id) AS 'Received'
FROM [CampaignRun] AS a
LEFT JOIN [CampaignRecipient] AS b
ON a.Id = b.CampaignRunId
WHERE a.CampaignId = 637
GROUP BY a.[Id], a.CampaignId,a.[Inserted]
ORDER BY a.[Inserted] DESC
Also ensure that you have index on foreign key in [CampaignRecipient] table on CampaignRunId column. It's considered a good practice.

Query Executing Problem

Using SQL 2005: “Taking too much time to execute”
I want to filter the date, the date should not display in holidays, and I am using three tables with Inner Join
When I run the below query, It taking too much time to execute, because I filter the cardeventdate with three table.
Query
SELECT
PERSONID, CardEventDate tmp_cardevent3
WHERE (CardEventDate NOT IN
(SELECT T_CARDEVENT.CARDEVENTDATE
FROM T_PERSON
INNER JOIN T_CARDEVENT ON T_PERSON.PERSONID = T_CARDEVENT.PERSONID
INNER JOIN DUAL_PRO_II_TAS.dbo.T_WORKINOUTTIME ON T_CARDEVENT.CARDEVENTDAY = DUAL_PRO_II_TAS.dbo.T_WORKINOUTTIME.DAYCODE
AND T_PERSON.TACODE = DUAL_PRO_II_TAS.dbo.T_WORKINOUTTIME.TACODE
WHERE (DUAL_PRO_II_TAS.dbo.T_WORKINOUTTIME.HOLIDAY = 'true')
)
)
ORDER BY PERSONID, CardEventDate DESC
For the above mentioned Query, there is any other way to do date filter.
Expecting alternative queries for my query?
I'm pretty sure that it's not the joined tables that is the problem, but rather the "not in" that makes it slow.
Try to use a join instead:
select m.PERSONID, m.CardEventDate
from T_PERSON p
inner join T_CARDEVENT c on p.PERSONID = c.PERSONID
inner join DUAL_PRO_II_TAS.dbo.T_WORKINOUTTIME w
on c.CARDEVENTDAY = w.DAYCODE
and p.TACODE = w.TACODE
and w.HOLIDAY = 'true'
right join tmp_cardevent3 m on m.CardEventDate = c.CardEventDate
where c.CardEventDate is null
order by m.PERSONID, m.CardEventDate desc
(There is a from clause missing from your query, so I don't know what table you are trying to get the data from.)
Edit:
Put tmp_cardevent3 in the correct place.
Have you created indices on all of the columns that you are using to do the joins? In particular, I'd consider indices on PERSONID in T_CARDEVENT, TACODE in both T_PERSON and T_WORKINOUTTIME, and HOLIDAY in T_WORKINOUTTIME.

Resources