Reputation: 1998
I'm new to SQL queries and I need to make a join starting from this query:
SELECT b.Name, a.*
FROM a INNER JOIN b ON a.VId = b.Id
WHERE b.SId = 100
AND a.Day >= '2016-05-05'
AND a.Day < '2016-05-09';
and adding 2 more columns to the first selected data (SCap and ECap from table c). From what I've tried my code looks like this:
SELECT b.Name,a.*,
c.MaxDay,
c.Cap,
FROM a INNER JOIN b
ON a.VId = b.Id
INNER JOIN
(SELECT VId,
MAX(TimestampLocal) AS MaxDay,
CAST (TimestampLocal AS DATE) AS Day,
Cap,
FROM Info
GROUP BY VId,
CAST (TimestampLocal AS DATE),
Cap) AS c
ON a.VId = c.VId
AND a.Day = c.Day
WHERE b.SId = 33
AND a.Day >= '2016-05-05'
AND a.Day < '2016-05-09';
But I get more rows than needed.
I need the earliest and the latest TimestampLocal for a given vehicle in a daterange. That would come from two records in Info, and each would have its proper values for Cap. For example: I have two Names with values inside table Info for 2 days (Name 1) and only one day for Name 2:
- Day 1 2016-05-07:
- Name 1: Values at 2:45, 10:10 and 3.10
- Name 2: Values at 5:13 and 8:22
- Day 2 2016-05-09:
- Name 1: Values at 4:13, 6:15 and 9:20
I need to display (if I select daterange: 2016-05-05
to 2016-05-09
) for Name 1 for SCap the value from 2016-05-07 from 2:45 and for ECap the value from 2016-05-09 from 9:20 and for Name 2 for SCap the value from 2016-05-07 from 5:13 and for ECap the value from 2016-05-07 from 8:22. This should be displayed in 2 lines.
Is there a way I can add those 2 columns into my query without adding more rows for the same Name?
EDIT! Table a I have:
VId | Day
5251 | 05/09/2016
5382 | 05/09/2016
Table b:
Id | Name
5251 | N1
5382 | N2
Table Info:
VId | TimestampLocal | Cap
5251 | 2016-05-09 11:33:46.2000000 +03:00 | 0
5251 | 2016-05-09 11:37:11.4000000 +03:00 | 7
5251 | 2016-05-09 11:38:11.4000000 +03:00 | 4
5251 | 2016-05-09 11:39:11.7000000 +03:00 | 2
5382 | 2016-05-09 09:30:56.6000000 -04:00 | 5
5382 | 2016-05-09 09:31:56.6000000 -04:00 | 3
And I need to display - if I select a daterange from 2016-05-03
to 2016-05-10
:
Id | Name | SCap | ECap
5251 | N1 | 0 | 2
5382 | N2 | 5 | 3
Upvotes: 3
Views: 649
Reputation: 1998
I found a solution for my query after some further investigations and here is what I managed to do:
SELECT b.Id,
b.Name,
c.S_Time,
c.E_Time,
s.Cap AS S_Cap,
e.Capa AS E_Cap,
FROM b
INNER JOIN (SELECT VId,
MIN(TimestampLocal) AS S_Time,
MAX(TimestampLocal) AS E_Time
FROM Info
where CAST (TimestampLocal AS DATE) >='2016-04-05'
and CAST (TimestampLocal AS DATE) <'2016-05-10'
GROUP BY VId
) AS c
ON b.Id = c.VId
INNER JOIN Info AS s
ON s.VId = c.VId
AND s.TimestampLocal = c.S_Time
INNER JOIN Info AS e
ON e.Vd = c.VId
AND e.TimestampLocal = c.E_Time
WHERE b.SId = 100
Upvotes: 0
Reputation: 49270
First, get the max and min timestamp for each id for a given date. Then join it twice, once with the max timestamp value and then with the min timestamp value for each id to tblinfo,to get the start and end cap values for those rows.
Add a where
clause with a date filter to filter for specific days.
with maxandmin as
(select vid
,max(timestamplocal) maxtime
,min(timestamplocal) mintime
from tblinfo
group by vid,cast(timestamplocal as date))
select m.vid,b.name,i1.cap as Scap,i2.cap as Ecap
from maxandmin m
join tblinfo i1 on m.vid=i1.vid and m.mintime = i1.timestamplocal
join tblinfo i2 on m.vid=i2.vid and m.maxtime = i2.timestamplocal
join tableb b on b.id=m.vid
Upvotes: 0
Reputation: 72205
You can use a CTE
with ROW_NUMBER
in order to retrieve the two records:
;WITH Info_CTE AS (
SELECT VId,
CAST (TimestampLocal AS DATE) AS Day,
Cap,
ROW_NUMBER() OVER (PARTITION BY VId
ORDER BY TimestampLocal) AS rn1,
ROW_NUMBER() OVER (PARTITION BY VId
ORDER BY TimestampLocal DESC) AS rn2
FROM Info
)
SELECT b.Name,
a.*,
c.Day,
c.Cap
FROM a
INNER JOIN b ON a.VId = b.Id
INNER JOIN Info_CTE AS c ON a.VId = c.VId AND
a.Day = c.Day AND
1 IN (c.rn1, c.rn2)
WHERE b.SId = 33
AND a.Day >= '2016-05-05'
AND a.Day < '2016-05-09';
If you want ECap
and SCap
as separate columns then instead of
c.Cap
you can use:
CASE WHEN c.rn1 = 1 THEN c.Cap END AS ECap,
CASE WHEN c.rn2 = 1 THEN c.Cap END AS SCap
Upvotes: 0