Issue with Running Total Still - sql-server

I still have an issue with working out the best way to calculate a running balance.
I am going to be using this code in a Rent Statement that I am going to produce in SSRS, but the problem I am having is that I can't seem to work out how to achieve a running balance.
SELECT rt.TransactionId,
rt.TransactionDate,
rt.PostingDate,
rt.AccountId,
rt.TotalValue,
rab.ClosingBalance,
ROW_NUMBER()OVER(PARTITION BY rt.AccountId ORDER BY rt.PostingDate desc) AS row,
CASE WHEN ROW_NUMBER()OVER(PARTITION BY rt.AccountId ORDER BY rt.PostingDate desc) = 1
THEN ISNULL(rab.ClosingBalance,0)
ELSE 0 end
FROM RentTransactions rt
--all accounts for the specific agreement
INNER JOIN (select raa.AccountId
from RentAgreementEpisode rae
inner join RentAgreementAccount raa on raa.AgreementEpisodeId = rae.AgreementEpisodeId
where rae.AgreementId=1981
) ij on ij.AccountId = rt.AccountId
LEFT JOIN RentBalance rab on rab.AccountId = rt.AccountId AND rt.PostingDate BETWEEN rab.BalanceFromDate AND isnull(rab.BalanceToDate,dateadd(day, datediff(day, 0, GETDATE()), 0))
What this gives me are the below results- I have included the results below -
So my code is sorting my transactions in the order I want and also is row numbering them in the correct order as well.
Where the Row Number is 1 - I need it to pull back the balance on that account at that point in time, which is what I am doing....BUT I am then unsure how I then get my code to start subtracting the proceeding row - so in this case The current figure of 1118.58 would need the Total Value in Row 2 = 91.65 subtracted from it - so the running balance for row 2 would be 1026.93 and so on...
Any help would be greatly appreciated.

Assuming you have all the transactions being returned in your query you can calculate a running total using the over clause, you just need to start at the beginning of your dataset rather than working backwards from your current balance:
declare #t table(d date,v decimal(10,2));
insert into #t values ('20170101',10),('20170102',20),('20170103',30),('20170104',40),('20170105',50),('20170106',60),('20170107',70),('20170108',80),('20170109',90);
select *
,sum(v) over (order by d
rows between unbounded preceding
and current row
) as RunningTotal
from #t
order by d desc
Output:
+------------+-------+--------------+
| d | v | RunningTotal |
+------------+-------+--------------+
| 2017-01-09 | 90.00 | 450.00 |
| 2017-01-08 | 80.00 | 360.00 |
| 2017-01-07 | 70.00 | 280.00 |
| 2017-01-06 | 60.00 | 210.00 |
| 2017-01-05 | 50.00 | 150.00 |
| 2017-01-04 | 40.00 | 100.00 |
| 2017-01-03 | 30.00 | 60.00 |
| 2017-01-02 | 20.00 | 30.00 |
| 2017-01-01 | 10.00 | 10.00 |
+------------+-------+--------------+

Related

Date span over tables

I want to show all profit centers a user had. The necessary information are in two tables.
TerritoryAssignment
+-------------0----------+------------+------------+--------------+
| TerritoryID | DBUserID | ValidFrom | ValidThru | AssignmentID |
+-------------+----------+------------+------------+--------------+
| T1 | 472 | 2019-03-01 | 2019-12-31 | 1389 |
| T4 | 472 | 2020-01-01 | 2020-10-31 | 2105 |
| T8 | 472 | 2020-11-01 | 2021-09-12 | 2226 |
| T12 | 472 | 2021-09-13 | 2021-11-30 | 2578 |
| T2 | 472 | 2021-12-01 | 9999-12-31 | 2659 |
+-------------+----------+------------+------------+--------------+
TerritoryDetails
+-----------+--------------+------------+------------+--------------------+
TerritoryID | ProfitCenter | ValidFrom | ValidThru | TerritoryDetailsID |
+-----------+--------------+------------+------------+--------------------+
| T2 | P05 | 2021-12-01 | 2022-04-30 | 983 |
| T2 | P18 | 2022-05-01 | 9999-12-31 | 1029 |
| T1 | P45 | 2012-09-01 | 9999-12-31 | 502 |
| T4 | P23 | 2020-01-01 | 9999-12-31 | 755 |
| T12 | P05 | 2020-01-01 | 9999-12-31 | 846 |
| T8 | P18 | 2020-01-01 | 9999-12-31 | 956 |
+-----------+--------------+------------+------------+--------------------+
Both tables are joined over the field TerritoryID.
As you can see, the user hat profit center P18 at two different time periods. Therefore a simple MIN and MAX with grouping is not possible. Also see that there are two records for profit center P05 which should be aggregated into one.
I want to get all Profit Centers a user had in the past including the exact start date and end date. The output could look like this:
+----------+------------+------------+--------------+
| DBUserID | ValidFrom | ValidThru | ProfitCenter |
+----------+------------+------------+--------------+
| 472 | 2019-03-01 | 2019-12-31 | P45 |
| 472 | 2020-01-01 | 2020-10-31 | P23 |
| 472 | 2020-11-01 | 2021-09-12 | P18 |
| 472 | 2021-09-13 | 2022-04-30 | P05 |
| 472 | 2022-05-01 | 9999-12-31 | P18 |
+----------+------------+------------+--------------+
The problem is:
A user can have different territory assignments over the time -> multiple entries in table TerritoryAssignment for a user.
Territory details can change -> multiple entries in table TerritoryDetails for a territory.
The profit center can be the same over several TerritoryDatails records.
The profit canter can be appear at another territory as well.
The start and end dates in the records of both tables are independent and therefore cannot used for a join.
I already tried some CTE with ROW_NUMBER() but was not successful. Here my last try, not giving the correct result:
SELECT
DBUserID,
ProfitCenter,
MIN(ValidFrom) AS IslandStartDate,
MAX(ValidThru) AS IslandEndDate
FROM
(
SELECT
*,
CASE WHEN Groups.PreviousEndDate >= ValidFrom THEN 0 ELSE 1 END AS IslandStartInd,
SUM(CASE WHEN Groups.PreviousEndDate >= ValidFrom THEN 0 ELSE 1 END) OVER (ORDER BY Groups.RN) AS IslandId
FROM
(
SELECT
ROW_NUMBER() OVER(ORDER BY DBUserID,ProfitCenter,TD.ValidFrom,TD.ValidThru) AS RN,
DBUserID,
ProfitCenter,
IIF(TA.ValidFrom<TD.ValidFrom,TD.ValidFrom,TA.ValidFrom) AS ValidFrom,
IIF(TA.ValidThru>TD.ValidThru,TD.ValidThru,TA.ValidThru) AS ValidThru,
LAG(TD.ValidFrom,1) OVER (ORDER BY DBUserID,ProfitCenter,TD.ValidFrom,TD.ValidThru) AS PreviousEndDate
FROM
dbo.TerritoryDetails TD INNER JOIN dbo.TerritoryAssignment TA ON TD.TerritoryID=TA.TerritoryID
WHERE TA.DBUserID=472
AND (
(TD.ValidFrom<=TA.ValidFrom AND TD.ValidThru>=TA.ValidFrom)
OR (TD.ValidFrom>=TA.ValidFrom AND TD.ValidThru<=TA.ValidThru)
OR (TD.ValidFrom<=TA.ValidThru AND TD.ValidThru>=TA.ValidThru)
)
) Groups
) Islands
GROUP BY
IslandId,DBUserID,ProfitCenter
ORDER BY
IslandStartDate desc
Does anybody can help?
The first problem here is finding intervals of time which overlap.
This actually turns out to be a fairly trivial expression. Given two intervals T1 and T2, they overlap if:
T1.start <= T2.end and T1.end >= T2.start
Here is a good explanation of why that works
The next problem is that once we have constructed the overlapped intervals, those intervals may be consecutive, ie, one interval starts the day after a prior interval ends. You want to "concatenate" those intervals. An example of this can be seen in your sample data for P05, where the following intervals exist:
2021-09-13 to 2021-11-30
2021-12-01 to 2022-04-30
And your desired result shows the total interval 2021-09-13 to 2022-04-30
We can use some running-sum "magic" to find consecutive intervals and merge them together.
Here is the complete logic broken up into distinct CTEs to make it easier to understand. Comments inline to explain the logic.
If you insert a select for each CTE in turn and look at the output up to that point it may help with understanding the overall logic.
create table #territoryassignment
(
TerritoryID char(3),
DBUserID int,
ValidFrom date,
ValidThru date,
AssignmentID int
);
create table #territoryDetails
(
TerritoryID char(3),
ProfitCenter char(3),
ValidFrom date,
ValidThru date,
TerritoryDetailsID int
);
insert #territoryassignment values
('T1 ', 472, '2019-03-01', '2019-12-31', 1389),
('T4 ', 472, '2020-01-01', '2020-10-31', 2105),
('T8 ', 472, '2020-11-01', '2021-09-12', 2226),
('T12', 472, '2021-09-13', '2021-11-30', 2578),
('T2 ', 472, '2021-12-01', '9999-12-31', 2659)
insert #territoryDetails values
('T2 ', 'P05', '2021-12-01', '2022-04-30', 983 ),
('T2 ', 'P18', '2022-05-01', '9999-12-31', 1029),
('T1 ', 'P45', '2012-09-01', '9999-12-31', 502 ),
('T4 ', 'P23', '2020-01-01', '9999-12-31', 755 ),
('T12', 'P05', '2020-01-01', '9999-12-31', 846 ),
('T8 ', 'P18', '2020-01-01', '9999-12-31', 956 );
-- Find overlapping intervals.
-- An overlap exists if T1.start <= T2.end and T1.end >= T2.start
-- so include that predicate in the join.
-- Where an overlap is found, construct a new interval consisting of the overlapped section
with intervals as
(
select ta.DBUserID,
td.ProfitCenter,
ValidFrom = iif(td.ValidFrom > ta.ValidFrom, td.ValidFrom, ta.ValidFrom),
ValidThru = iif(td.ValidThru < ta.ValidThru, td.ValidThru, ta.ValidThru)
from #territoryAssignment ta
join #territoryDetails td on td.territoryID = ta.territoryId
and td.validFrom <= ta.ValidThru
and td.ValidThru >= ta.ValidFrom
),
-- For each interval,
-- if the prior interval ended yesterday
-- then it is not gapped, otherwise it is.
gaps as
(
select DbUserId,
ProfitCenter,
ValidFrom,
ValidThru,
gap = iif
(
lag(ValidThru) over
(
partition by DBUserId, profitCenter
order by ValidFrom asc
) = dateadd(day, -1, ValidFrom),
0, 1
)
from intervals
),
-- gapCount is the running total number of gaps seen
-- for a given user and profit center
-- in order of the interval start dates.
-- Consecutive intervals will have the same gapCount
-- non consecutive intervals will have an ever increasing gapCount.
grouped as
(
select DBUserId,
ProfitCenter,
ValidFrom,
ValidThru,
gapCount = sum(gap) over
(
partition by DBUserId, ProfitCenter
order by ValidFrom
rows unbounded preceding
)
from gaps
)
-- "Merge" consecutive intervals by grouping on the gapCount
select DBUserId,
ProfitCenter,
ValidFrom = min(ValidFrom),
ValidThru = max(ValidThru)
from grouped
group by DBUserId,
ProfitCenter,
gapCount
order by DBUserId,
ProfitCenter,
ValidFrom;

Selecting unique records based on date of effect, ending on date of discontinue

I have an interesting conundrum and I am using SQL Server 2012 or SQL Server 2016 (T-SQL obviously). I have a list of products, each with their own UPC code. These products have a discontinue date and the UPC code gets recycled to a new product after the discontinue date. So let's say I have the following in the Item_UPCs table:
Item Key | Item Desc | UPC | UPC Discontinue Date
123456 | Shovel | 0009595959 | 2018-04-01
123456 | Shovel | 0007878787 | NULL
234567 | Rake | 0009595959 | NULL
As you can see, I have a UPC that gets recycled to a new product. Unfortunately, I don't have an effective date for the item UPC table, but I do in an items table for when an item was added to the system. But let's ignore that.
Here's what I want to do:
For every inventory record up to the discontinue date, show the unique UPC associated with that date. An inventory record consists of the "Inventory Date", the "Purchase Cost", the "Purchase Quantity", the "Item Description", and the "Item UPC".
Once the discontinue date is over with (e.g.: it's the next day), start showing only the UPC that is in effect.
Make sure that no duplicate data exists and the UPCs are truly being "attached" to each row per whatever the date is in the query.
Here is an example of the inventory details table:
Inv_Key | Trans_Date | Item_Key | Purch_Qty | Purch_Cost
123 | 2018-05-12 | 123456 | 12.00 | 24.00
108 | 2018-03-22 | 123456 | 8.00 | 16.00
167 | 2018-07-03 | 234567 | 12.00 | 12.00
An example query:
SELECT DISTINCT
s.SiteID
,id.Item_Key
,iu.Item_Desc
,iu.Item_Department
,iu.Item_Category
,iu.Item_Subcategory
,iu.UPC
,iu.UPC_Discontinue_Date
,id.Trans_Date
,id.Purch_Cost
,id.Purch_Qty
FROM Inventory_Details id
INNER JOIN Item_UPCs iu ON iu.Item_Key = id.Item_Key
INNER JOIN Sites s ON s.Site_Key = id.Site_Key
The real query I have is far too long to post here. It has three CTEs and the resultant query. This is simply a mockup. Here is an example result set:
Site_ID | Item_Key | Item_Desc | Item_Department | Item_Category | UPC | UPC_Discontinue Date | Trans_Date | Purch_Cost | Purch_Qty
2457 | 123456 | Shovel | Digging Tools | Shovels | 0009595959 | 2018-04-01 | 2018-03-22 | 16.00 | 8.00
2457 | 123456 | Shovel | Digging Tools | Shovels | 0007878787 | NULL | 2018-03-22 | 16.00 | 8.00
2457 | 234567 | Rakes | Garden Tools | Rakes | 0009595959 | NULL | 2018-07-03 | 12.00 | 12.00
2457 | 123456 | Shovel | Digging Tools | Shovels | 0007878787 | NULL | 2018-05-12 | 24.00 | 12.00
Do any of you know how I can "assign" a UPC to a specific range of dates in my query and then "assign" an updated UPC to the item for every effective date thereafter?
Many thanks!
Given your current Item_UPC table, you can generate effective start dates from the Discontinue Date using the LAG analytic function:
With Effective_UPCs as (
select [Item_Key]
, [Item_Desc]
, [UPC]
, coalesce(lag([UPC_Discontinue_Date])
over (partition by [Item_Key]
order by coalesce( [UPC_Discontinue_Date]
, datefromparts(9999,12,31))
),
lag([UPC_Discontinue_Date])
over (partition by [UPC]
order by coalesce( [UPC_Discontinue_Date]
, datefromparts(9999,12,31))
)) [UPC_Start_Date]
, [UPC_Discontinue_Date]
from Item_UPCs i
)
select * from Effective_UPCs;
Which yields the following Results:
| Item_Key | Item_Desc | UPC | UPC_Start_Date | UPC_Discontinue_Date |
|----------|-----------|------------|----------------|----------------------|
| 123456 | Shovel | 0007878787 | 2018-04-01 | (null) |
| 123456 | Shovel | 0009595959 | (null) | 2018-04-01 |
| 234567 | Rake | 0009595959 | 2018-04-01 | (null) |
This function produces a fully open ended interval where both the start and discontinue dates could be null indicating that it's effective for all time. To use this in your query simply reference the Effective_UPCs CTE in place of the Item_UPCs table and add a couple additional predicates to take the effective dates into consideration:
SELECT DISTINCT
s.SiteID
,id.Item_Key
,iu.Item_Desc
,iu.Item_Department
,iu.Item_Category
,iu.Item_Subcategory
,iu.UPC
,iu.UPC_Discontinue_Date
,id.Trans_Date
,id.Purch_Cost
,id.Purch_Qty
FROM Inventory_Details id
INNER JOIN Effective_UPCs iu
ON iu.Item_Key = id.Item_Key
and (iu.UPC_Start_Date is null or iu.UPC_Start_Date < id.Trans_Date)
and (iu.UPC_Discontinue_Date is null or id.Trans_Date <= iu.UPC_Discontinue_Date)
INNER JOIN Sites s ON s.Site_Key = id.Site_Key
Note that the above query uses a partially open range (UPC_Start_Date < trans_date <= UPC_Discontinue_Date instead of <= for both inequalities) this prevents transactions occurring exactly on the discontinue date from matching both the prior and next Item_Key record. If transactions that occur exactly on the discontinue date should match the new record and not the old simply swap the two inequalities:
and (iu.UPC_Start_Date is null or iu.UPC_Start_Date <= id.Trans_Date)
and (iu.UPC_Discontinue_Date is null or id.Trans_Date < iu.UPC_Discontinue_Date)
instead of
and (iu.UPC_Start_Date is null or iu.UPC_Start_Date < id.Trans_Date)
and (iu.UPC_Discontinue_Date is null or id.Trans_Date <= iu.UPC_Discontinue_Date)

How to sum up values in a column for each week number?

I need to sum up values from Money column for each WeekNumber.
Now I have view:
WeekNumber | DayTime | Money
---------------------------------------
1 | 2012-01-01 | 20.4
1 | 2012-01-02 | 30.5
1 | 2012-01-03 | 55.1
2 | 2012-02-01 | 67.3
2 | 2012-02-02 | 33.4
3 | 2012-03-01 | 11.8
3 | 2012-03-04 | 23.9
3 | 2012-03-05 | 34.3
4 | 2012-04-01 | 76.6
4 | 2012-04-02 | 90.3
Tsql:
SELECT datepart(week,DayTime) AS WeekNumber, DayTime, Money FROM dbo.Transactions
In conclusion, I would like to get something like this:
WeekNumber | DayTime | Sum
---------------------------------------
1 | 2012-01-01 | 106
2 | 2012-02-02 | 100.7
3 | 2012-03-03 | 470
4 | 2012-04-01 | 166.9
DayTime should be random for each Week Number but exists in column DayTime from view above.
Please, be free to write your ideas. Thanks.
SELECT datepart(week,DayTime) AS WeekNumber
, MIN(DayTime) DayTime --<-- Instead of random get first date from your data in that week
, SUM(Money) AS [Sum]
FROM dbo.Transactions
GROUP BY datepart(week,DayTime)
Try this
SELECT datepart(week,DayTime) AS WeekNumber, SUM(Money) FROM dbo.Transactions GROUP BY WeekNumber
As you will have number of rows for each week you cannot get DayTime with the same table. There are other ways to add that too like JOIN
Change your SQL to sum the money column. Like this
SELECT
datepart(week,DayTime) AS WeekNumber,
DayTime, Money = SUM(Money)
FROM dbo.Transactions
GROUP BY datepart(week,DayTime),DayTime
SELECT datepart(week, DayTime) AS WeekNumber
,MIN(DayTime)
,SUM(MONEY)
FROM dbo.Transactions
GROUP BY datepart(week, DayTime)

Complex SQL query, not sure where to start

I have a tough one here I think. I have the following tables:
[Assets]
AssetId | Name
1 | Acura NSX
2 | Dodge Ram
[Assignments]
AssignmentId | AssetId | StartMileage | EndMileage | StartDate | EndDate
1 | 1 | 8000 | 10000 | 4/1/2015 | 5/1/2015
2 | 1 | 10000 | 16000 | 9/15/2015 | 1/5/2016
3 | 2 | 51000 | NULL | 1/1/2016 | NULL
[Reminders]
ReminderId | AssetId | Name | Distance | Time | Active
1 | 1 | Oil Change | 3000 (miles)| 3 (months)| 1
2 | 1 | Tire Rotation | 5000 | 6 | 0
3 | 2 | Oil Change | 3000 | 3 | 1
4 | 2 | Air Filter | 50000 | 48 | 1
[Maintenance]
MaintenanceId | AssetId | ReminderId | Mileage | Date | Vendor
1 | 1 | 1 | 10000 | 5/1/2015 | Jiffy Lube
2 | 2 | 3 | 51000 | 6/1/2015 | Dealership
I need a query that will join these 4 tables and return something like the following.
Name | Name | Current Mileage | Last Mileage | Last Date
Acura NSX | Oil Change | 16000 | 10000 | 5/1/2015
Dodge RAM | Oil Change | 51000 | 51000 | 6/1/2015
Dodge RAM | Air Filter | 51000 | -- | --
I need to take the distance threshold from the Reminders table and add it to the mileage from the Maintenance table then compare it to the start and end mileage from the Assignments table. If the threshold is greater than the start or end mileage then select the asset name, the name of the reminder, the current mileage (start or end mileage from Assignments, whichever is greater), and mileage and date from the last maintenance for that reminder. I need to do the same for time threshold. Add it to the date from the Maintenance table then compare it to today's date. If it's greater then display the asset.
Can one of you SQL gurus help me with this please?
UPDATE:
SELECT
v.Name,
r.Name AS Reminder,
a.CurrentMileage,
i.MaintenanceMileage,
i.MaintenanceDate
FROM
Assets v
LEFT JOIN
(SELECT AssetId,
COALESCE(EndMileage, StartMileage) AS CurrentMileage,
ROW_NUMBER() OVER (PARTITION BY AssetId
ORDER BY AssignmentId DESC) AS window_id
FROM Assignments) a
ON v.AssetId = a.AssetId
AND a.window_id = 1
JOIN
Reminders r
ON v.AssetId = r.AssetId
AND r.ActiveFlag = 1
LEFT JOIN
(SELECT AssetId,
ReminderId,
MAX(Mileage) AS MaintenanceMileage,
MAX([Date]) AS MaintenanceDate
FROM Maintenances
GROUP BY AssetId, ReminderId) i
ON r.ReminderId = i.ReminderId
AND (a.CurrentMileage > (NULLIF(i.MaintenanceMileage, 0) + r.DistanceThreshold))
OR (GETDATE() > DATEADD(m, r.[TimeThreshold], i.MaintenanceDate))
Here is a starting point:
SELECT v.Name AS [Asset Name], r.Name AS Reminder, a.CurrentMileage,
m.Mileage + r.Distance AS [Last Mileage], m.[Date] AS [Last Date]
FROM Assets v
JOIN ( -- get the latest relevant row as window_id = 1
SELECT AssetId, COALESCE(EndMileage, StartMileage) AS CurrentMileage,
COALESCE(EndDate, StartDate) AS AssignDate,
ROW_NUMBER() OVER (partition by AssetId
order by COALESCE(EndDate, StartDate) DESC) AS window_id
FROM Assignments
) a
ON v.AssetId = a.AssetId
AND a.window_id = 1
JOIN Reminders r
ON v.AssetId = r.AssetId
AND r.Active = 1
LEFT JOIN Maintenance m
ON r.AssetId = m.AssetId
AND r.ReminderId = m.ReminderId
-- corrected
AND ((a.CurrentMileage > (NULLIF(m.Mileage, 0) + r.Distance))
-- slightly oversimplified
OR (GETDATE() > DATEADD(m, r.[Time], COALESCE(m.[Date], a.AssignDate))))
The date calculations are slightly oversimplified because they use the latest assignment dates. What you would really want is a column Assets.InServiceDate that would anchor the time before the first maintenance would be due. But this will get you started.

Sum worked hours

I have a issues table where users can log worked hours and estimate hours that looks like this
id | assignee | task | timespent | original_estimate | date
--------------------------------------------------------------------------
1 | john | design | 2 | 3 | 2013-01-01
2 | john | mockup | 2 | 3 | 2013-01-02
3 | john | design | 2 | 3 | 2013-01-01
4 | rick | mockup | 5 | 4 | 2013-01-04
And I need to sum and group the worked and estimated hours by task and date to get this
assignee | task | total_spent | total_estimate | date
------------------------------------------------------------------
john | design | 4 | 6 | 2013-01-01
john | mockup | 2 | 3 | 2013-01-02
rick | design | 5 | 4 | 2013-01-04
Ok, this is easy, I've already got this:
SELECT assignee, task, SUM(timespent) as total_spent, SUM(original_estimate) AS total_estimate, date FROM issues GROUP BY assignee, task, date
My problem is I need to also show the assignees that did not logged hours on any task that day, I mean:
assignee | task | total_spent | total_estimate | date
------------------------------------------------------------------
john | design | 4 | 6 | 2013-01-01
john | mockup | 2 | 3 | 2013-01-02
rick | design | 5 | 4 | 2013-01-04
pete | design | 0 | 0 | 2013-01-01
pete | mockup | 0 | 0 | 2013-01-02
liz | design | 0 | 0 | 2013-01-04
liz | mockup | 0 | 0 | 2013-01-04
The goal is to draw a chart like this http://jsfiddle.net/uUjst/embedded/result/
You need the Assignees in their own separate table to join from.
SELECT tblAssignee.Name, task, SUM(timespent) as total_spent, SUM(original_estimate) AS total_estimate, date
FROM tblAssignee
LEFT JOIN issue ON issues.assignee = tblAssignee.Name
GROUP BY tblAssignee.Name, task, date
Assuming that you have a user table, but not a tasks or dates table... meaning that we have to derive these values from the values present in issues:
;WITH dates AS (
SELECT DISTINCT date
FROM issues
), tasks AS (
SELECT DISTINCT task
FROM issues
)
SELECT
u.user as assignee,
t.task,
SUM(i.timespent) as total_spent,
SUM(i.original_estimate) AS total_estimate,
d.date
FROM
users u CROSS JOIN
dates d CROSS JOIN
tasks t LEFT OUTER JOIN
issues i ON
i.assignee = u.user
AND i.task = t.task
AND i.date = d.date
GROUP BY u.user, t.task, d.date
SELECT
A.name,
task,
ISNULL(SUM(timespent), 0) as total_spent,
ISNULL(SUM(original_estimate), 0) AS total_estimate,
date
FROM Assignee A
LEFT JOIN issue
ON issues.assignee = A.Name
GROUP BY A.name, task, date

Resources