Reputation: 1998
I'm new to SQL queries and I need to make a join starting from this query:
SELECT b.Name AS VehicleName,
a.*
FROM VehicleDay AS a
INNER JOIN
Vehicles AS b
ON a.VehicleId = b.Id
WHERE b.SiteId = 100
AND a.Day >= '2016-04-22'
AND a.Day < '2016-04-28';
and adding 6 more columns from the Info data table:
Starting (first value of the day) & Ending (last of day) - Cumulative [Cml] - Current Capacity [Cap] - Total charge [Chrg]
So I need to add on at the far right S Cml | E Cml | S Cap | E Cap | S Chrg | E Chrg
In the Info table I get values for the same VehicleId on different period of day and I need to select the first and the last data for each day in a daterange.
So far my query looks like this:
SELECT b.Name AS VehicleName,
a.*,
c.MaxDay,
c.Cumulative,
c.CurrentCapacity,
c.TotalCharge
FROM VehicleDay AS a
INNER JOIN
Vehicles AS b
ON a.VehicleId = b.Id
INNER JOIN
(SELECT VehicleId,
MAX(TimestampLocal) AS MaxDay,
CAST (TimestampLocal AS DATE) AS Day,
Cumulative,
CurrentCapacity,
TotalCharge
FROM Info
GROUP BY VehicleId,
CAST (TimestampLocal AS DATE),
Cumulative, CurrentCapacity, TotalCharge) AS c
ON a.VehicleId = c.VehicleId
AND a.Day = c.Day
WHERE b.SiteId = 100
AND a.Day >= '2016-04-22'
AND a.Day < '2016-04-28';
But the second query returns more rows that the first one and I need to display the number of rows as the first one.
Is there a way I can add those 6 columns into my query without adding more rows?
Upvotes: 0
Views: 133
Reputation: 351298
The reason for the duplicates is that you group also by Cumulative, CurrentCapacity, TotalCharge
, which may have different values on the same day. So then that GROUP BY
will serve multiple records per day and so multiply the records already selected from the two other tables.
You could first just get the MIN/MAX values of the time stamps, and then with these values, join the table Info
twice again, once to retrieve the columns related to the MIN time, and once for those related to the MAX time:
SELECT b.Name AS VehicleName,
a.*,
c.S_Time,
c.E_Time,
s.Cumulative AS S_Cml,
e.Cumulative AS E_Cml,
s.CurrentCapacity AS S_Cap,
e.CurrentCapacity AS E_Cap,
s.TotalCharge AS S_Chrg,
e.TotalCharge AS E_Chrg
FROM VehicleDay AS a
INNER JOIN Vehicles AS b
ON a.VehicleId = b.Id
LEFT JOIN (SELECT VehicleId,
CAST (TimestampLocal AS DATE) AS Day,
MIN(TimestampLocal) AS S_Time,
MAX(TimestampLocal) AS E_Time
FROM Info
GROUP BY VehicleId,
CAST (TimestampLocal AS DATE)
) AS c
ON a.VehicleId = c.VehicleId
AND a.Day = c.Day
LEFT JOIN Info AS s
ON s.VehicleId = c.VehicleId
AND s.TimestampLocal = c.S_Time
LEFT JOIN Info AS e
ON e.VehicleId = c.VehicleId
AND e.TimestampLocal = c.E_Time
WHERE b.SiteId = 100
AND a.Day >= '2016-04-22'
AND a.Day < '2016-04-28'
There is one condition: the combination VehicleId
and TimestampLocal
must be unique, or you'll still get more rows than expected.
Upvotes: 1