Sql 从右连接重复行

Sql 从右连接重复行,sql,left-join,right-join,Sql,Left Join,Right Join,我的应用程序在一天中的3个不同时间段中保存至少一次需要记录的日志。因此,理想情况下,每天有3个日志,每个日志都有一个唯一的时间段ID。我需要编写一个异常报告MSSQL 2008,该报告将显示任何给定的一天何时错过了一个时间段。我有一个LogTimePeriods表,每个时间段包含3行。Logs表包含LogTimePeriodID,因此我不需要通过应用程序执行任何逻辑来查看日志所属的时间段 我知道我需要右/左连接,以尝试匹配给定日期每个日志行的所有LogTimePeriodID。我似乎不能取得任何

我的应用程序在一天中的3个不同时间段中保存至少一次需要记录的日志。因此,理想情况下,每天有3个日志,每个日志都有一个唯一的时间段ID。我需要编写一个异常报告MSSQL 2008,该报告将显示任何给定的一天何时错过了一个时间段。我有一个LogTimePeriods表,每个时间段包含3行。Logs表包含LogTimePeriodID,因此我不需要通过应用程序执行任何逻辑来查看日志所属的时间段

我知道我需要右/左连接,以尝试匹配给定日期每个日志行的所有LogTimePeriodID。我似乎不能取得任何进展。感谢您的帮助!谢谢你的阅读

编辑:下面的所需输出

日期|对数周期ID 6/3 | 3 6/5 | 2
6/5 | 3

您的SQL FIDLE设置为使用MYSQL,而不是SQL Server 2008,因此我无法根据您的数据测试我的答案:但是,根据我对您的需求的理解,并假设您正在查询SQL 2008数据库,下面的例子应该适用于您,对我的表变量的引用显然会被实际的表所取代

DECLARE @StartDate DATE = '06/04/2014'
DECLARE @EndDate DATE = GETDATE();
DECLARE @LogTimePeriod TABLE (LogTimePeriodID INT IDENTITY(1,1), TimePeriod VARCHAR(20))
INSERT INTO @LogTImePeriod (TimePeriod) SELECT '00:00 - 07:59'
INSERT INTO @LogTImePeriod (TimePeriod) SELECT '08:00 - 15:59'
INSERT INTO @LogTImePeriod (TimePeriod) SELECT '16:00 - 23:59'


DECLARE @logs TABLE (LogDataID INT IDENTITY(1,1), LogDate DATE, SomeInformation VARCHAR(10), LogTimePeriodID INT)
INSERT INTO @logs (SomeInformation, LogDate, LogTimePeriodID) SELECT 'abc', '6/4/2014', 1
INSERT INTO @logs (SomeInformation, LogDate, LogTimePeriodID) SELECT 'def', '6/4/2014', 2
INSERT INTO @logs (SomeInformation, LogDate, LogTimePeriodID) SELECT 'ghi', '6/4/2014', 3
INSERT INTO @logs (SomeInformation, LogDate, LogTimePeriodID) SELECT 'abc', '6/5/2014', 1
INSERT INTO @logs (SomeInformation, LogDate, LogTimePeriodID) SELECT 'def', '6/5/2014', 2;


WITH dates AS (
     SELECT CAST(@StartDate AS DATETIME) 'date'
     UNION ALL
     SELECT DATEADD(dd, 1, t.date) 
       FROM dates t
      WHERE DATEADD(dd, 1, t.date) <= @EndDate)

SELECT ltp.LogTimePeriodID, ltp.TimePeriod, dates.date
FROM 
    @LogTimePeriod ltp
     INNER JOIN 
    dates ON 1=1
     LEFT JOIN 
    @logs ld ON 
        ltp.LogTimePeriodID = ld.LogTimePeriodID AND
        dates.date = ld.LogDate
WHERE ld.LogDataID IS NULL
 OPTION (MAXRECURSION 1000) -- 0 is unlimited, 1000 limits to 1000 rows 
SQLServer2008使用EXCEPT关键字从第一个记录集中减去第二个记录集。 在这种情况下,可以生成所有可能的日志并从日志表中删除这些日志,这将使日志不在表中

SELECT DISTINCT StartDateTime, StartTime, EndTime
FROM   Logs
       CROSS JOIN LogTimePeriods
EXCEPT
SELECT StartDateTime, StartTime, EndTime
FROM   LogTimePeriods ltp
       LEFT  JOIN logs l ON l.LogTimePeriodID = ltp.LogTimePeriodID
ORDER BY StartDateTime, StartTime

将数据转换为SQLServer 2008后,查询的预期结果是什么?未完成日志的日期和LogTimePeriodID列表。在我的小提琴中,6月3日只有三分之二的时间段完成,6月5日只有三分之一的时间段完成两次。请参阅我对原始问题的编辑,例如输出。是!!加入日期列表是我遗漏的关键部分,这是相当聪明的。我也很抱歉,我不知道SQL FIDLE可以设置为另一个DB引擎。谢谢你今天教我两件事:不客气。有一个比我聪明得多的人提出了日期列表技巧,它在这里很有效,因为你需要用所有可能的组合有效地生成一组数据,然后才能找出缺少哪些组合。