SQL:显示选择人员记录的给定日期范围的信息

时间:2013-07-23 14:11:58

标签: sql-server-2008 tsql

首先,对这个含糊不清的主题道歉,我不知道怎么说这个。

在SQL中,我有两个表,表A = People,表B =他们在特定日期的位置。

Table A
PK  Name
1   Fred
2   John
3   James

Table B
PK  Date        PersFK  Location
1   2013-01-01  1       Office
2   2013-01-01  2       Meeting
3   2013-01-02  1       Office
4   2013-01-03  1       Meeting
5   2013-01-04  3       Mars
6   2013-01-04  2       Moon

对于People表中的每个记录,我想显示其数据范围的位置,即使表B中没有设置位置

Date        Name        Location
2013-01-01  Fred        Office
2013-01-01  John        Meeting
2013-01-01  James       NULL
2013-01-02  Fred        Office
2013-01-02  John        NULL
2013-01-02  James       NULL
2013-01-03  Fred        Office
2013-01-03  John        NULL
2013-01-03  James       NULL
2013-01-04  Fred        NULL
2013-01-04  John        Moon
2013-01-04  James       Mars
2013-01-05  Fred        NULL
2013-01-05  John        NULL
2013-01-05  James       NULL

这是我到目前为止所提出的,但是当一个人在表b中没有设置位置时,它没有显示记录。也许我过于复杂的事情或者无法解决问题。任何帮助将不胜感激

DECLARE @YEAR INT = 2013
DECLARE @Month INT = 7

--Movements
DECLARE @tblMovements TABLE (PersPK INT, PersName VARCHAR(MAX), PersDept VARCHAR(MAX), PersOffice VARCHAR(MAX), PersCompany VARCHAR(MAX), MovDate DATE, MovLocation VARCHAR(MAX))

--Dates
DECLARE @StartDate DATETIME = DateAdd(yy, @Year-1900, DateAdd(m,  @Month - 1, 0)) 
DECLARE @EndDate DATETIME
DECLARE @tblDates TABLE (DateIN DATETIME)

SELECT @StartDate = DATEADD(s,0,DATEADD(mm, DATEDIFF(m,0,@StartDate),0)) --FirstDayOfMonth
SELECT @EndDate = DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@StartDate)+1,0)) --LastDayOfMonth

;WITH Dates AS (
SELECT @StartDate AS myDate
UNION ALL
SELECT DATEADD(DAY,1,myDate)
FROM Dates
WHERE DATEADD(DAY,1,myDate) <= @EndDate
)

INSERT INTO @tblDates (DateIN)
SELECT myDate
FROM Dates
OPTION (MAXRECURSION 0)

INSERT INTO @tblMovements (PersPK, PersName, PersDept, PersOffice, PersCompany, MovDate, MovLocation)
SELECT 
    P.Pers_PK
    ,P.Pers_FName + ' ' + P.Pers_SName + ' (' + P.Pers_Ext + ')'  [Name]
    ,P.DeptShortName
    ,P.ShortName
    ,P.CompanySName
    ,CONVERT(DATE, M.[Mov_Date], 103) [Mov Date]
    ,M.[Mov_Location]
FROM [Pers_People_T] P
LEFT JOIN Pers_Movements_T M ON M.Pers_FK = P.Pers_PK AND M.Mov_Date Between @StartDate AND DateAdd(dd,0,@EndDate)
WHERE P.Pers_Department_FK = 6
AND P.Active = 1

SELECT * FROM @tblDates D
FULL JOIN @tblMovements M ON D.DateIN = M.MovDate

编辑:感谢t-clausen.dk,这就是我最终提出来的

declare @year int = 2013
declare @month int = 7

declare @tableA table(PK int, name varchar(5))
declare @tableB table(PK int, Date date, PersFK int, Location varchar(10))

--Dates
DECLARE @StartDate DATETIME = DateAdd(yy, @Year-1900, DateAdd(m,  @Month - 1, 0)) 
DECLARE @EndDate DATETIME
SELECT @StartDate = DATEADD(s,0,DATEADD(mm, DATEDIFF(m,0,@StartDate),0)) --FirstDayOfMonth
SELECT @EndDate = DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,@StartDate)+1,0)) --LastDayOfMonth
DECLARE @tblDates TABLE (DateIN DATETIME)

;WITH Dates AS (
SELECT @StartDate AS myDate
UNION ALL
SELECT DATEADD(DAY,1,myDate)
FROM Dates
WHERE DATEADD(DAY,1,myDate) <= @EndDate
)

INSERT INTO @tblDates (DateIN)
SELECT myDate
FROM Dates
OPTION (MAXRECURSION 0)


insert @tableA values (1, 'Fred'), (2, 'John'),(3, 'James')

insert @TableB values(1,   '2013-01-01',  1, 'Office'),
(2,   '2013-07-01',  2,      'Meeting'),
(3,   '2013-07-02',  1,      'Office'),
(4,   '2013-07-03',  1,      'Meeting'),
(5,   '2013-07-04',  3,      'Mars'),
(6,   '2013-07-04',  2,      'Moon')

select coalesce(c.DateIN, b.Date) Date, a.name, b.PersFK, b.location
from 
(
SELECT * FROM @tblDates
) c
cross join
@tableA a
left join
@tableB b
on 
a.PK = b.PersFk
and c.DateIN = b.date
order by Date, Name

1 个答案:

答案 0 :(得分:1)

也许这可以让你的生活更轻松:

declare @year int = 2013
declare @month int = 7

declare @tableA table(PK int, name varchar(5))
declare @tableB table(PK int, Date date, PersFK int, Location varchar(10))

insert @tableA values (1, 'Fred'), (2, 'John'),(3, 'James')

insert @TableB values(1,   '2013-01-01',  1, 'Office'),
(2,   '2013-07-01',  2,      'Meeting'),
(3,   '2013-07-02',  1,      'Office'),
(4,   '2013-07-03',  1,      'Meeting'),
(5,   '2013-07-04',  3,      'Mars'),
(6,   '2013-07-04',  2,      'Moon')


select coalesce(c.Date, b.Date) Date, a.name, b.PersFK, b.location
from 
(
select dateadd(month, (@year-1900)*12+@month - 1, number) Date
from
master..spt_values
where type = 'p' 
and number < day(dateadd(month, (@year-1900)*12+@month, -1))
) c
cross join
@tableA a
left join
@tableB b
on 
a.PK = b.PersFk
and c.date = b.date
order by Date, Name