从右连接重复行

时间:2014-06-05 14:34:53

标签: sql left-join right-join

我的应用程序会保存在白天的3个不同时段中的每一个期间至少需要进行一次的日志。理想情况下,每天3个日志,每个日志都有一个唯一的时间段ID。我需要编写一个异常报告(MSSQL 2008),它将显示任何特定日期错过的时间段。我有一个LogTimePeriods表,每个时间段包含3行。 Logs表包含LogTimePeriodID,所以我不需要做任何逻辑来查看日志所属的时间段(通过应用程序完成)。

我知道我需要一些左/右连接的东西来尝试匹配给定日期的每个Log行的所有LogTimePeriodID。我似乎无法取得任何进展。任何帮助表示赞赏!谢谢你的阅读。

SQL Fiddle

编辑:下面的所需输出

日期| LogPeriodID
6/3 | 3
6/5 | 2
6/5 | 3

2 个答案:

答案 0 :(得分:1)

您的SQL小提琴设置为使用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 

答案 1 :(得分:0)

SQLServer 2008使用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

SQLFiddle demo 将您的数据转换为SQLServer 2008