2011-08-22 5 views
1

tout d'abord, la question execuse plus, mais je vais essayer de le mettre le plus simplement possible ...groupe multiple fondé sur la date par requête T-SQL

Je suis en train d'écrire une sorte de rapport de requête, mais j'ai un problème pour obtenir les résultats souhaités. Le problème:

table des employés

Id | Name     
--------------- 
1 | John Smith 
2 | Alan Jones 
3 | James Jones 

table Tâche

Id | Title | StartDate | EmployeeId | Estimate (integer - ticks) 
---------------------------------------------------------------------------- 
1 | task1 | 21.08.2011 | 1   | 90000000000 
2 | task2 | 21.08.2011 | 1   | 150000000 
3 | task3 | 22.08.2011 | 2   | 1230000000 

Question:

Comment obtenir le résumé de l'estimation par jour, groupés, mais pour inclure tous les employés?

Comme ceci:

Date   | EmployeeId | EmployeeName | SummaryEstimate 
------------------------------------------------------------- 
19.08.2011  | 1   | John Smith  | NULL 
19.08.2011  | 2   | Alan Jones  | NULL 
19.08.2011  | 3   | James Jones  | NULL 
20.08.2011  | 1   | John Smith  | NULL 
20.08.2011  | 2   | Alan Jones  | NULL 
20.08.2011  | 3   | James Jones  | NULL 
21.08.2011  | 1   | John Smith  | 90150000000 
21.08.2011  | 2   | Alan Jones  | NULL 
21.08.2011  | 3   | James Jones  | NULL 
22.08.2011  | 1   | John Smith  | NULL 
22.08.2011  | 2   | Alan Jones  | 1230000000 
22.08.2011  | 3   | James Jones  | NULL 

Ce que je fais actuellement est que j'ai une table "dates" avec des jours 30 annees. Je suis parti rejoindre et groupe par cette table pour obtenir d'autres dates incluses aussi. Eh bien, voici la requête:

SELECT dates.value, employee.Id, employee.Name, sum(task.Estimate) 

    FROM TableOfDates as dates 
    left join Tasks as task on (dates.value = convert(varchar(10), task.StartTime, 101)) 
    left join Employees as employee on (employee.Id = task.EmployeeId) 

    WHERE dates.value >= '2011-08-19' and dates.value < '2011-08-22' 

    GROUP BY dates.value, employee.Id, employee.Name 

    ORDER BY dates.value, employee.Id 

L'appel de conversion consiste à obtenir la partie date de la colonne DateTime.

Le résultat que je reçois est:

Date   | EmployeeId | EmployeeName | SummaryEstimate 
------------------------------------------------------------- 
19.08.2011  | NULL   | NULL   | NULL 
20.08.2011  | NULL   | NULL   | NULL 
21.08.2011  | 1   | John Smith  | 90150000000  
22.08.2011  | 2   | Alan Jones  | 1230000000 

Je suis là la moitié du chemin, je reçois les dates qui ne sont pas dans les deux la base tables jointes (employés et tâches) mais je ne peux pas avoir aussi tous les employés inclus comme dans le tableau montré avant celui-ci.

J'ai essayé d'effectuer une jointure croisée, puis des sous-requêtes, mais peu de chance. Toute aide sera la bienvenue ! Nous vous remercions d'avoir le temps de passer par tout cela, je l'espère, j'été assez clair ...

+1

Le tableau immédiatement après la question, tous les employés inclus ainsi que les dates –

Répondre

4
SELECT DE.DateValue, DE.EmployeeId, DE.EmployeeName, sum(task.Estimate) 

FROM 
( SELECT 
    D.value AS DateValue 
    , E.Id AS EmployeeId 
    , E.Name AS EmployeeName 
    FROM 
    TableOfDates D  
    CROSS JOIN Employees E) DE 
left join Tasks as task on DE.DateValue = convert(varchar(10), task.StartTime, 101) 
    AND DE.EmployeeId = task.EmployeeId 

WHERE DE.DateValue >= '2011-08-19' and DE.DateValue < '2011-08-22' 

GROUP BY DE.DateValue, DE.EmployeeId, DE.EmployeeName 

ORDER BY DE.DateValue, DE.EmployeeId 
+0

tour est joué! Merci beaucoup ... –

+0

Marek était plus rapide que moi. :) Une note: GROUP BY DE.DateValue, DE.EmployeeId, DE.EmployeeName peut-être en utilisant Emp_Id et Emp_name est superflu ... nous pouvons utiliser un seul champ ... mais c'est seulement une petite note --- donc + 1 :) – Max

2

Notez que cette solution offre la possibilité de déposer la table de jour que vous pouvez utiliser un CTE récursive dynamique au lieu.

Les autres CTE: s (Employés et Tâches) peuvent être remplacés par les tables réelles.

DECLARE @startDate DATETIME = '2011-08-01' 
DECLARE @endDate DATETIME = '2011-09-01' 

;WITH Employees(Id,Name) 
AS 
(
SELECT 1, 'John Smith' 
UNION ALL 
SELECT 2, 'Alan Jones' 
UNION ALL 
SELECT 3, 'James Jones' 
) 
,Tasks (Id, Title, StartDate, EmployeeId, Estimate) 
AS 
(
SELECT 1, 'task1', '2011-08-21', 1, 90000000000 
UNION ALL 
SELECT 2, 'task2', '2011-08-21', 1, 150000000 
UNION ALL 
SELECT 3, 'task3', '2011-08-22', 2, 1230000000 
) 
,TableOfDates(value) 
AS 
(
    SELECT DATEADD(DAY, DATEDIFF(DAY, 0, @startDate), 0) 
    UNION ALL 
    SELECT DATEADD(DAY, 1, value) 
    FROM TableOfDates 
    WHERE value < @endDate 
) 

SELECT dates.value 
     ,employee.Id 
     ,employee.Name 
     ,SUM(task.Estimate) AS SummaryEstimate 
FROM TableOfDates dates 
CROSS JOIN Employees employee 
LEFT JOIN Tasks task 
    ON dates.value = task.StartDate 
    AND (employee.Id = task.EmployeeId) 
WHERE dates.value >= '2011-08-19' 
    AND dates.value < '2011-08-26' 
GROUP BY 
    dates.value 
    ,employee.Id 
    ,employee.Name 
ORDER BY 
    dates.value 
    ,employee.Id 
2

utilisez cette requête:

create table #T_dates (id_date int identity(1,1),inp_date datetime) 
create table #T_tasks (id_task int identity(1,1),key_date int, key_emp int, est int) 
create table #T_emp (id_emp int identity(1,1),name varchar(50)) 

insert #T_dates (inp_date) values ('08.19.2011') 
insert #T_dates (inp_date) values ('08.20.2011') 
insert #T_dates (inp_date) values ('08.21.2011') 
insert #T_dates (inp_date) values ('08.22.2011') 
insert #T_dates (inp_date) values ('08.23.2011') 
insert #T_dates (inp_date) values ('08.24.2011') 
--select * from #T_dates 

insert #T_emp (name) values ('John Smith') 
insert #T_emp (name) values ('Alan Jones') 
insert #T_emp (name) values ('James Jones') 
--select * from #T_emp 

insert #T_tasks (key_date,key_emp,est) values (4,1,900000) 
insert #T_tasks (key_date,key_emp,est) values (4,1,15000) 
insert #T_tasks (key_date,key_emp,est) values (5,2,123000) 
--select * from #T_tasks 

select inp_date,id_emp,name,EST 
from #T_emp 
cross join #T_dates 
left join 
(
select key_date,key_emp,SUM(est) 'EST' from #T_tasks group by key_date,key_emp 
) Gr 
    ON Gr.key_emp = id_emp and Gr.key_date = id_date 
where inp_date >= '2011-08-19' and inp_date <= '2011-08-22' 
order by inp_date,id_emp