SQL joining same columns in different ways - sql-server

select top 1000
f.*, s.TimeZoneCode as TimeZoneOrigin,
s2.TimeZoneCode as TimeZoneDestination,
tz.StandardVariation as VariationOrigin,
tz2.StandardVariation as VariationDestination,
tzv.Variation as TimeVariation,
tzv2.Variation as TimeVariation2
from
REZNVWB01.MIT.HVResearchDataSetDraft1 f
inner join
REZNVOD01.dbo.Station s on s.StationCode = f.TripOriginLocationCode
inner join
REZNVOD01.dbo.Station s2 on s2.StationCode = f.TripDestinationLocationCode
inner join
REZNVOD01.dbo.TimeZone tz on tz.TimeZoneCode = s.TimeZoneCode
inner join
REZNVOD01.dbo.TimeZone tz2 on tz2.TimeZoneCode = s.TimeZoneCode
inner join
REZNVOD01.dbo.TimeZoneVariation tzv on tzv.TimeZoneCode = s.TimeZoneCode
and tzv.EndUTC >= BookingDate
and tzv.StartUTC <= BookingDate
I have one table with StartUTC and EndUTC and timezonevariation for each row. I want to look at BookingTime, and gain the timezonevariation for when bookingtime is between StartUTC and EndUTC.
What do I need to change in this code?
inner join
REZNVOD01.dbo.TimeZoneVariation tzv on tzv.TimeZoneCode = s.TimeZoneCode
and tzv.EndUTC >= BookingDate
and tzv.StartUTC <= BookingDate
Is this code correct if the TimeZoneVariation code StartUTC and EndUTC are between conditions (IE startUTC might be 5:00 and endUTC might be 10:00, I want the TimeZoneVariation value where BookingDate is between startUTC and endUTC)

To answer your first question - merely by the logic - you can use the BETWEEN statement that could make your intent clearer. BETWEEN is inclusive, which means it includes the values at either end of the range in the comparison:
INNER JOIN REZNVOD01.dbo.TimeZoneVariation tzv
ON tzv.TimeZoneCode = s.TimeZoneCode AND
BookingDate BETWEEN tzv.EndUTC AND tzv.StartUTC
However, you're not clarifying whether "BookingDate" is a field within "f" or a variable. If it's a variable, make sure you prepend it with the commercial at (#) and if it's from "f", please declare it as such (E.G. f.BookingDate). This practice will make your code clearer to those reading it.
As to your final query ... it might be beneficial to spell out your table aliases instead of abbreviating them so much (I like to break my lines down and do indentation to help visualize the join relationships):
SELECT TOP 1000
f.*,
origStation.TimeZoneCode AS TimeZoneOrigin,
destStation.TimeZoneCode AS TimeZoneDestination,
origTz.StandardVariation AS VariationOrigin,
destTz.StandardVariation AS VariationDestination,
origTzv.Variation AS TimeVariationOrigin,
destTzv.Variation AS TimeVariationDestination
FROM
REZNVWB01.MIT.HVResearchDataSetDraft1 AS f
INNER JOIN REZNVOD01.dbo.Station AS origStation
ON origStation.StationCode=f.TripOriginLocationCode
INNER JOIN REZNVOD01.dbo.Station AS destStation
ON destStation.StationCode=f.TripDestinationLocationCode
INNER JOIN REZNVOD01.dbo.TimeZone AS origTz
ON origTz.TimeZoneCode=origStation.TimeZoneCode
INNER JOIN REZNVOD01.dbo.TimeZone AS destTz
ON destTz.TimeZoneCode=destStation.TimeZoneCode
INNER JOIN REZNVOD01.dbo.TimeZoneVariation AS origTzv
ON origTzv.TimeZoneCode = origStation.TimeZoneCode AND
f.BookingDate BETWEEN origTzv.EndUTC AND origTzv.StartUTC
INNER JOIN REZNVOD01.dbo.TimeZoneVariation AS destTzv
ON destTzv.TimeZoneCode = destStation.TimeZoneCode AND
f.BookingDate BETWEEN destTzv.EndUTC AND destTzv.StartUTC
I don't quite understand your last question. Could you please restate it?
Thanks!

Related

Multiple INNER JOIN SELECT query not returning data

This is a stored procedure to select the full details of a wine.
It takes as a parameter a storage location ID.
This builds properly and is similar in structure to many sp's I have written that work,
however it returns no data. Is there something I am missing?
CREATE PROCEDURE [sp_retrieveInventory_Full]
(
#StorageLocationID [int]
)
AS
BEGIN
SELECT [WineName],
[RackID],
[RackColumn],
[RackRow],
[WineTypeID],
[WineVarietyID],
[VintnerName],
[dbo].[Vintner].[Country],
[dbo].[Vintner].[StateProvince],
[dbo].[Vintner].[Region],
[VendorName],
[Vintage],
[PurchaseDate],
[PurchasePrice],
[BottleSizeID],
[ABV],
[DrinkByDate],
[FoodType],
[TastingNotes],
[RatedBy],
[RatingScore]
FROM [dbo].[StorageLocation]
INNER JOIN [dbo].[Wine]
ON [dbo].[StorageLocation].[WineID] = [dbo].[Wine].[WineID]
INNER JOIN [dbo].[Vintner]
ON [dbo].[Vintner].[VintnerID] = [dbo].[Wine].[VintnerID]
INNER JOIN [dbo].[Vendor]
ON [dbo].[Vendor].[VendorID] = [dbo].[Wine].[VendorID]
INNER JOIN [dbo].[Pairing]
ON [dbo].[Pairing].[PairingID] = [dbo].[Wine].[PairingID]
INNER JOIN [dbo].[Rating]
ON [dbo].[Rating].[RatingID] = [dbo].[Wine].[RatingID]
WHERE [dbo].[StorageLocation].[StorageLocationID] = #storageLocationID
END
GO
When a query reruns no result it's because no records exists that satisfy the conditions in it's where clause, or, in case of queries that contains inner joins, at least one of the joins on condition returns no records.
The easiest way to figure out what join is messing up your query is to start removing the joins one by one, but to do that, you have to first change the select clause.
What I like to do is this: Start with all the joins except the last one - see if it returns any records:
SELECT 1
FROM [dbo].[StorageLocation]
INNER JOIN [dbo].[Wine]
ON [dbo].[StorageLocation].[WineID] = [dbo].[Wine].[WineID]
INNER JOIN [dbo].[Vintner]
ON [dbo].[Vintner].[VintnerID] = [dbo].[Wine].[VintnerID]
INNER JOIN [dbo].[Vendor]
ON [dbo].[Vendor].[VendorID] = [dbo].[Wine].[VendorID]
INNER JOIN [dbo].[Pairing]
ON [dbo].[Pairing].[PairingID] = [dbo].[Wine].[PairingID]
-- INNER JOIN [dbo].[Rating]
-- ON [dbo].[Rating].[RatingID] = [dbo].[Wine].[RatingID]
WHERE [dbo].[StorageLocation].[StorageLocationID] = #storageLocationID
If not, comment out the next join and run the query again. Rinse and repeat.
Please note, however, that there might be more than one inner join that prevents the query from returning records.

Removing timestamp from date using INNERJOIN in SQL Server

I found a lot of things here, but nothing helped me. I can remove timestamp, but I can't remove it when I use INNER JOIN. I tried many things, but it does not work.
Here it is what am I trying to do:
SELECT
CAST(CURRENT_TIMESTAMP as DATE) "END_DATE", LO_ID
FROM
dbo.LO as L
INNER JOIN
dbo.IL as I ON L.LO_ID = I.LO_ID
INNER JOIN
dbo.PO as P ON P.LO_ID = I.LO_ID
INNER JOIN
dbo.CO as C ON P.CO_ID = C.ID
WHERE
P.LO = 7
I get error at LO_ID. How can I remove timestamp when I use INNER JOIN ?
I've also tried CONVERT method instead of CAST.
PS: This is the result I want to get:
SELECT * FROM loan.LOANS as L
INNER JOIN insurance.INSURANCES as I ON L.LOAN_ID = I.LOAN_ID
INNER JOIN insurance.POLICIES as P ON P.LOAN_ID = I.LOAN_ID
INNER JOIN insurance.COMPANIES as C ON P.COMPANY_ID = C.ID WHERE P.LOAN_ID = 7
This works fine and this is what I expect for, but in all Date has a timestamp and I just want to remove that timestamp
What is the problem with this query ?
SELECT CONVERT(date, [L.END_DATE]) as LOAN_END_DATE,
CONVERT(date, [I.END_DATE]) as INSURANCE_END_DATE,
L.LOAN_ID
FROM loan.LOANS as L
INNER JOIN insurance.INSURANCES as I ON L.LOAN_ID = I.LOAN_ID
INNER JOIN insurance.POLICIES as P ON P.LOAN_ID = I.LOAN_ID
INNER JOIN insurance.COMPANIES as C ON P.COMPANY_ID = C.ID WHERE P.LOAN_ID = 7
You should be able to remove the time part of every returned field using the convert function. It doesn't matter if the returned fields come from the main table or the joined tables.

IS NULL being ignored

I am trying to run a query in T-SQL to pull back a data set based on a column being null.
This is a simplified version of the code:
SELECT
T1.Col1, T1.Col2,
T1.Col3, T1.Col4
FROM
table1 AS T1
INNER JOIN
table2 AS T2 ON T1.Col2 = T2.Col3
WHERE
T2.Col4 IS NULL
Problem is, the result includes rows where T2.Col4 are NULL and also not NULL, it's like the WHERE clause doesn't exist.
Any ideas would be greatly
UPDATE - full version of code:
SELECT
M.ref
,C.cname
,CL.clname
,C.ccity
,M.productLine
,M.code
,CL.date
,M.dept
,DPT.group
,TK2.tkname
,TK2.tkdept
FROM DB.dbo.manage AS M
OUTER JOIN DB.dbo.ClientManageRelationship AS CMR
ON CMR.RelatedEntityID = M.EntityID
OUTER JOIN DB.dbo.Client AS C
ON C.EntityID = CMR.EntityID
INNER JOIN DB.dbo.ManageCustomerRelationship AS MCR
ON MCR.EntityID = M.EntityID
INNER JOIN DB.dbo.Customer AS CL
ON CL.EntityID = MCR.RelatedID
INNER JOIN DB.dbo.timek AS TK
ON TK.tki = M.tkid
LEFT JOIN (SELECT Group = division, [Department] = newdesc, deptcode FROM DB.csrt.vw_rep_p_l_dept) AS DPT
ON tkdept = DPT.dept
LEFT JOIN (SELECT Name = TK2.tkfirst + ' ' + TK2.tklast, TK2.tki, TK2.dept, TK2.loc FROM DB.dbo.timek as TK2 WITH(NOLOCK)) AS TK2
ON TK2.tki = M.tkid
WHERE DPT.Department = 'Casualty'
AND UPPER (C.ClientName) LIKE '%LIMITED%'
AND CL.date > '31/12/2014'
AND CL.Date IS NULL
AND TK.tkloc = 'loc1' OR TK.tkloc = 'loc2'
ORDER BY M.ref
My first answer would be because you're using INNER JOIN. This only returns matches between the 2 tables. TRY FULL OUTER JOIN which will return all values regardless of matches and will include NULLS.
If you were looking to return all rows regardless of matches including NULLS from only one of the tables then use RIGHT or LEFT JOIN.
Say i had 2 tables ('Person' and 'Figure'). Not every person may have entered a figure on any one day. But an example may be i want to return all people regardless of whether they entered a figure or not on a certain day.
My initial approach to this would be a LEFT join because i want to return of all the people(left table) regardless of there being any matches in the figure table(right table)
FROM Person P
LEFT JOIN Figure F
ON P.ID = F.ID
This would produce a result such as
Name Figure
Sam 20
Ben 30
Matt NULL
Simon NULL
Whereas,
An inner join would produce only matching values not including nulls
Name Figure
Sam 20
Ben 30
Left join works the same way as right join but in the opposite direction. This is most likely the problem you were facing. But i hope this helped
I think the problem is in the last part of the where condition.
You should use brackets.
`WHERE DPT.Department = 'Casualty'
AND UPPER (C.ClientName) LIKE '%LIMITED%'
AND CL.date > '31/12/2014'
AND CL.Date IS NULL
AND (TK.tkloc = 'loc1' OR TK.tkloc = 'loc2')`
or
`WHERE DPT.Department = 'Casualty'
AND UPPER (C.ClientName) LIKE '%LIMITED%'
AND CL.date > '31/12/2014'
AND CL.Date IS NULL
AND TK.tkloc IN ('loc1', 'loc2')`

How to join one select with another when the first one not always returns a value for specific row?

I have a complex query to retrieve some results:
EDITED QUERY (added the UNION ALL):
SELECT t.*
FROM (
SELECT
dbo.Intervencao.INT_Processo, analista,
ETS.ETS_Sigla, ATC.ATC_Sigla, PAT.PAT_Sigla, dbo.Assunto.SNT_Peso,
CASE
WHEN ETS.ETS_Sigla = 'PE' AND (PAT.PAT_Sigla = 'LIB' OR PAT.PAT_Sigla = 'LBR') THEN (0.3*SNT_Peso)
WHEN ETS.ETS_Sigla = 'CD' THEN (0.3*SNT_Peso)*0.3
ELSE SNT_Peso
END AS PESOAREA,
CASE
WHEN a.max_TEA_FimTarefa IS NULL THEN a.max_TEA_InicioTarefa
ELSE a.max_TEA_FimTarefa
END AS DATA_INICIO_TERMINO,
ROW_NUMBER() OVER (PARTITION BY ATC.ATC_Sigla, a.SRV_Id ORDER BY TEA_FimTarefa DESC) AS seqnum
FROM dbo.Tarefa AS t
INNER JOIN (
SELECT
MAX(dbo.TarefaEtapaAreaTecnica.TEA_InicioTarefa) AS max_TEA_InicioTarefa,
MAX (dbo.TarefaEtapaAreaTecnica.TEA_FimTarefa) AS max_TEA_FimTarefa,
dbo.Pessoa.PFJ_Descri AS analista, dbo.AreaTecnica.ATC_Id, dbo.Tarefa.SRV_Id
FROM dbo.TarefaEtapaAreaTecnica
LEFT JOIN dbo.Tarefa ON dbo.TarefaEtapaAreaTecnica.TRF_Id = dbo.Tarefa.TRF_Id
LEFT JOIN dbo.AreaTecnica ON dbo.TarefaEtapaAreaTecnica.ATC_Id = dbo.AreaTecnica.ATC_Id
LEFT JOIN dbo.ServicoAreaTecnica ON dbo.TarefaEtapaAreaTecnica.ATC_Id = dbo.ServicoAreaTecnica.ATC_Id
AND dbo.Tarefa.SRV_Id = dbo.ServicoAreaTecnica.SRV_Id
INNER JOIN dbo.Pessoa ON dbo.Pessoa.PFJ_Id = dbo.ServicoAreaTecnica.PFJ_Id_Analista
GROUP BY dbo.AreaTecnica.ATC_Id, dbo.Tarefa.SRV_Id, dbo.Pessoa.PFJ_Descri
) AS a ON t.SRV_Id = a.SRV_Id
INNER JOIN dbo.TarefaEtapaAreaTecnica AS TarefaEtapaAreaTecnica_1 ON
t.TRF_Id = TarefaEtapaAreaTecnica_1.TRF_Id
AND a.ATC_Id = TarefaEtapaAreaTecnica_1.ATC_Id
AND a.max_TEA_InicioTarefa = TarefaEtapaAreaTecnica_1.TEA_InicioTarefa
LEFT JOIN AreaTecnica ATC ON TarefaEtapaAreaTecnica_1.ATC_Id = ATC.ATC_Id
LEFT JOIN Etapa ETS ON TarefaEtapaAreaTecnica_1.ETS_Id = ETS.ETS_Id
LEFT JOIN ParecerTipo PAT ON TarefaEtapaAreaTecnica_1.PAT_Id = PAT.PAT_Id
LEFT OUTER JOIN dbo.Servico ON a.SRV_Id = dbo.Servico.SRV_Id
INNER JOIN dbo.Intervencao ON dbo.Servico.INT_Id = dbo.Intervencao.INT_Id
LEFT JOIN dbo.Assunto ON dbo.Servico.SNT_Id = dbo.Assunto.SNT_Id
) t
The result is following:
It works good, the problem is that I was asked that if when a row is not present on this query, it must contain values from another table (ServicoAreaTecnica), so I got this query for the other table based on crucial information of the first query. So if I UNION ALL I get this:
Query1 +
UNION ALL
SELECT INN.INT_Processo,
PES.PFJ_Descri,
NULL, --ETS.ETS_Sigla,
ART.ATC_Sigla,
NULL ,--PAT.PAT_Sigla,
ASS.SNT_Peso,
NULL, --PESOAREA
NULL, --DATA_INICIO_TERMINO
NULL --seqnum
FROM dbo.ServicoAreaTecnica AS SAT
INNER JOIN dbo.AreaTecnica AS ART ON ART.ATC_Id = SAT.ATC_Id
INNER JOIN dbo.Servico AS SER ON SER.SRV_Id = SAT.SRV_Id
INNER JOIN dbo.Assunto AS ASS ON ASS.SNT_Id = SER.SNT_Id
INNER JOIN dbo.Intervencao AS INN ON INN.INT_Id = SER.INT_Id
INNER JOIN dbo.Pessoa AS PES ON PES.PFJ_Id = SAT.PFJ_Id_Analista
The result is following:
So what I want to do is to remove row number 1 because row number 2 exists on the first query, I think I got it explained better this time. The result should be only row number 1, row number 2 would appear only if query 1 doesn't retrieve a row for that particular INN.INT_Processo.
Thanks!
Ok, there are two ways to reduce your record set. Given that you've already written the code to produce the table with the extra rows, it might be easiest to just add code to reduce that:
Select * from
(Select *
, Row_Number() over
(partition by IntProcesso, Analista order by ISNULL(seqnum, 0) desc) as RN
from MyResults) a
where RN = 1
This will assign row_number 1 to any rows that came from your first query, or to any rows from the second query that do not have matches in the first query, then filter out extra rows.
You could also use outer joins with isnull or coalesce, as others have suggested. Something like this:
Select ISNULL(a.IntProcesso, b.IntProcesso) as IntProcesso
, ISNULL(a.Analista, b.Analista) as Analista
, ISNULL(a.ETSsigla, b.ETSsigla) as ETSsigla
[repeat for the rest of your columns]
from Table1 a
full outer join Table2 b
on a.IntProcesso = b.IntProcesso and a.Analista = b.Analista
Your code is hard to read, because of the lengthy names of everything (and to be honest, the fact that they're in a language I don't speak also makes it a lot harder).
But how about: replacing your INNER JOINs with LEFT JOINs, adding more LEFT JOINs to draw in the alternative tables, and introducing ISNULL clauses for each variable you want in the results?
If you do something like ... Query1 Right Join Query2 On ... that should get only the rows in Query2 that don't appear in Query 1.

Query Optimizer can't push predicate past rollup? HINTs doesn't work also

This is the schema :
And this is the sql that as I understand is too complex for SQL Optimizer:
SELECT * FROM
(
select pp.Id as PaymentPartId, b.Id as BudgetId, grouping(bp.ID) as g1 , sum(pp.Amount) PaymentsSum, sum(bp.Amount) BudgetSum
from Projects pr
inner join Payments p ON pr.Id = p.ProjectID
inner join PaymentParts pp ON p.Id = pp.PaymentId
inner join Budgets b ON pr.Id = b.ProjectID
inner join Budgetparts bp ON b.Id = bp.BudgetId
group by pp.Id, b.Id, rollup(bp.ID)
) x
WHERE x.PaymentPartId = 777
SQLFIDDLE: http://sqlfiddle.com/#!6/aa74e/11 (with autogenerated data)
What I expect: execution plan should contain index seek on x.PaymentPartId. Why? Because this query is equivalent to:
select pp.Id as PaymentPartId, b.Id as BudgetId, grouping(bp.ID) as g1, sum(pp.Amount) PaymentsSum, sum(bp.Amount) BudgetSum
from Projects pr
inner join Payments p ON pr.Id = p.ProjectID
inner join PaymentParts pp ON p.Id = pp.PaymentId
inner join Budgets b ON pr.Id = b.ProjectID
inner join Budgetparts bp ON b.Id = bp.BudgetId
WHERE pp.Id = 777
group by pp.Id, b.Id, rollup(bp.ID)
...and the last query uses index seek.
But SQL Optimizer not only refuse to use the index but ignore all hints (I propose you to expirement wiht sqlfiddle - it is really interesting).
So the question is: am I right that it is impossible to force SQL Server Optimizer to use index seek there? It seems like rollup is something that split sql optimizer "optimization frame" to two parts and it makes it impossible to optimize WHOLE query.
P.S. For those who votes for closing this "non-programming question": try to put optimizer hints (sqlfiddle is ready to test your programming skills!).
Why hints doesn't work? - Roman Pokrovskij
It is in the documentation:
http://technet.microsoft.com/en-us/library/ms181714.aspx
Query hints can be specified only in the top-level query, not in subqueries

Resources