我尝试创建一个SQL查询/存储过程来计算特定团队某一天正在进行的应用程序数量。
我遇到问题的方法如下:当应用程序转移给另一个用户时,当天的计数不应重复计算(转移当天每个团队的计数),并且应转到转移的用户
我的桌子
**Users**
Id || Name || TeamId
---------------------------------
1 User 1 1
2 User 2 2
**Application**
Id || Name
-------------
1 Application1
**ApplicationUser**
Id || ApplicationId || UserId || AssignedDate || UnassignedDate
----------------------------------------------------------
1 1 1 2018-03-01 2018-03-02
2 1 2 2018-03-02 2018-03-03
所以在存储过程中我发送一个日期作为参数,我想要返回的结果如下。
Date || Team 1 || Team 2 || Total
-------------------------------------------
2018-03-02 0 1 1
所以,如果我将所有结果放在一起,它们就会像这样。
Date || Team 1 || Team 2 || Total
-------------------------------------------
2018-02-28 0 0 0
2018-03-01 1 0 1
2018-03-02 0 1 1
2018-03-03 0 1 1
非常感谢你提前:)
答案 0 :(得分:0)
试试这个:
在这里,我定义表变量并插入您提供的数据:
declare @users table (id int, name varchar(10), teamid int)
insert into @users values (1, 'user1', 1),(2, 'user2',2)
declare @application table (id int, name varchar(15))
insert into @application values (1, 'application1')
declare @applicationuser table (id int, applicationid int, userid int, assigneddate date, unassigneddate date)
insert into @applicationuser values (1,1,1,'2018-03-01','2018-03-02'),(2,1,2,'2018-03-02','2018-03-03')
--here I sum values for each team using cumulative sum
select [date],
sum(team1) over (order by [date] rows between unbounded preceding and current row) [team1],
sum(team2) over (order by [date] rows between unbounded preceding and current row) [team2],
sum(total) over (order by [date] rows between unbounded preceding and current row) [total]
from (
--here I am pivoting inner query, replacing NULL values using COALESCE
select [date],
coalesce(max(case when teamid = 1 then value end), 0) [team1],
coalesce(max(case when teamid = 2 then value end), 0) [team2],
coalesce(max(case when teamid = 1 then value end), 0) + coalesce(max(case when teamid = 2 then value end), 0) [total]
from (
--here I join assigned and unassigned dates with team ids
select [AU].assigneddate [date], [U].teamid, 1 [value] from @applicationuser [AU]
join @users [U] on [AU].userid = [U].id
union all
select [AU].unassigneddate, [U].teamid, -1 from @applicationuser [AU]
join @users [U] on [AU].userid = [U].id
) a
group by [date]
) a
为了更好地理解这一点,分别尝试每个查询,即首先执行大多数内部查询,然后用外部查询包装并查看结果。通过这种方式,您可以了解每一步的情况。
答案 1 :(得分:0)
最好使用日期表处理这类查询。如果您的数据库中没有数据库,我强烈建议您购买一个。
同时,您可以使用内联表值函数或查询中的派生表动态创建日期表(注意我添加了一个额外的打开应用程序):
-- Declare test data
declare @users table (id int, name varchar(10), teamid int);
declare @application table (id int, name varchar(15));
declare @applicationuser table (id int, applicationid int, userid int, assigneddate date, unassigneddate date);
insert into @users values (1, 'user1', 1),(2, 'user2',2);
insert into @application values (1, 'application1'),(2, 'application1');
insert into @applicationuser values (1,1,1,'2018-03-01','2018-03-02'),(2,1,2,'2018-03-02','2018-03-03'),(2,2,2,'2018-03-02','2018-03-05');
-- Find the maximum date range possible to create a dates table that covers all possible application periods
declare @MinDate date = (select min(AssignedDate) from @applicationuser);
declare @MaxDate date = (select max(UnassignedDate) from @applicationuser);
-- This is a derived table that simply returns 10 rows
with t(t) as(select * from(values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(t))
-- This then CROSS JOINs the 10 rows to create 10*10*10*10*10 = 100,000 rows
-- Then uses the ROW_NUMBER function to add a number of days to the @MinDate value, to get a table of incrementing dates
,d(d) as(select top(datediff(day,@MinDate,@MaxDate)+1) dateadd(day,row_number() over (order by (select null))-1,@MinDate) from t,t t2,t t3,t t4,t t5)
select d.d -- Output is a row per date and teamid where there was an open application.
,u.teamid -- When grouped together this gives you a COUNT of open applications by teamid
,count(1) as OpenApplications
from d
join @ApplicationUser as au
on d.d between au.assigneddate and au.unassigneddate
join @users as u
on au.userid = u.id
group by d.d
,u.teamid
order by d.d
,u.teamid
输出:
+------------+--------+------------------+
| d | teamid | OpenApplications |
+------------+--------+------------------+
| 2018-03-01 | 1 | 1 |
| 2018-03-02 | 1 | 1 |
| 2018-03-02 | 2 | 2 |
| 2018-03-03 | 2 | 2 |
| 2018-03-04 | 2 | 1 |
| 2018-03-05 | 2 | 1 |
+------------+--------+------------------+
我故意不pivot
编辑您的数据以匹配您想要的输出,因为这几乎总是一个坏主意。随着您的团队数量的变化,您输出的列数和名称将发生变化,这将需要不断维护。相反,您应该只输出一组正常数据,并在最终到达表示层后将pivot
留给表示层。
答案 2 :(得分:0)
这个用法是否完整:
DECLARE @users TABLE (id INT, name VARCHAR(10), teamid INT)
INSERT INTO @users VALUES (1, 'user1', 1),(2, 'user2',2)
DECLARE @application TABLE (id INT, name VARCHAR(15))
INSERT INTO @application VALUES (1, 'application1')
DECLARE @applicationuser TABLE (id INT, applicationid INT, userid INT, assigneddate DATE, unassigneddate DATE)
INSERT INTO @applicationuser VALUES (1,1,1,'2018-03-01','2018-03-02'),(2,1,2,'2018-03-02','2018-03-03')
DECLARE @assignment TABLE([date] DATE,teamid INT,[value] INT)
INSERT INTO @assignment
SELECT [AU].assigneddate [date], [U].teamid, 1 [value]
FROM @applicationuser [AU]
JOIN @users [U] ON [AU].userid = [U].id
INSERT INTO @assignment
SELECT [AU].unassigneddate, [U].teamid,
CASE WHEN LEAD(AssignedDate) OVER(ORDER BY [AU].id)=unassigneddate
THEN -1
ELSE
1
END
FROM @applicationuser [AU]
JOIN @users [U] ON [AU].userid = [U].id
SELECT b.[date],
CASE WHEN t1.teamid=1
THEN 1
ELSE
0
END AS Team1,
CASE WHEN t1.teamid=2
THEN 1
ELSE
0
END AS Team2,
total
FROM
(
SELECT [date], MAX([value]) AS Total
FROM @assignment
group by [date]
)b
INNER JOIN @assignment t1 ON b.Total=t1.Value AND b.[date]=t1.[date]
ORDER BY b.[date]
答案 3 :(得分:0)
非常感谢您的所有答案。
我自己也在尝试这个,我似乎找到了问题的答案。
DECLARE @DATE DATETIME
SELECT @DATE = '20180301'
SELECT ApplicationId, Max(UnassignedDate) as UnassignedDate
INTO #TempApplicationUsers
FROM ApplicationUsers
WHERE @DATE > DAteAdd(Day, -1, AssignedDate) and (@DATE < UnassignedDate OR
UnassignedDate is NULL)
Group BY ApplicationId
SELECT * From #TempApplicationUsers
SELECT UserId, COUNT(*) FROM ApplicationUsers, #TempApplicationUsers
WHERE ApplicationUsers.ApplicationId = #TempApplicationUsers.ApplicationId
and ISNULL(ApplicationUsers.UnassignedDate, 0) =
ISNULL(#TempApplicationUsers.UnassignedDate, 0)
GROUP BY UserId
DROP TABLE #TempApplicationUsers
这将返回当天每个用户的计数,从中我可以通过users表中的TeamId得到每个团队的计数。
再次感谢您