Sql 考虑不在时间范围内的记录
我们正在查询一个RFID数据库,并计算每小时特定时间段的读取量。但当没有记录时,时间框架就不会显示出来,这是应该的。然而,我们想报告的是,在这段时间内没有任何记录 以下是查询:Sql 考虑不在时间范围内的记录,sql,sql-server,sql-server-2005,Sql,Sql Server,Sql Server 2005,我们正在查询一个RFID数据库,并计算每小时特定时间段的读取量。但当没有记录时,时间框架就不会显示出来,这是应该的。然而,我们想报告的是,在这段时间内没有任何记录 以下是查询: select date_tr, right('0000'+ convert(varchar,timeofday),2) + '00 - ' + right('0000'+ convert(varchar,timeofday+1),2) + '00' as timeofday, count(placa) reads fro
select
date_tr,
right('0000'+ convert(varchar,timeofday),2) + '00 - ' + right('0000'+ convert(varchar,timeofday+1),2) + '00' as timeofday,
count(placa) reads
from
(select distinct gi.placa,
convert(varchar(10), tr.inDate,101) as date_tr,
datepart(hour, tr.inDate) timeofday
from
RFIDTransaction tr, RFIDGeneralInformation gi
where
gi.tag = tr.tag
and inDate between current_timestamp - 1 and current_timestamp
and inLoc = 'GATE IN'
and gi.removed = 0
and tr.removed = 0
group by convert(varchar(10), tr.inDate,101), datepart(hour, tr.inDate), gi.placa) xx
group by date_tr, timeofday
order by date_tr, timeofday
此查询的输出如下所示:
date_tr timeofday reads
01/19/2014 0500 - 0600 12
01/19/2014 0600 - 0700 15
01/19/2014 0800 - 0900 22
...
select
intervals.interval,
mytable.*
from
mytable
right join (
select '0000-0100' as interval
union all
select '0100-0200' as interval
union all
...
select '2300-2400' as interval ) intervals
on
mytable.interval = intervals.interval
现在,我们需要显示时间范围0700-0800,读取为零
我该怎么做
非常感谢最简单的方法是创建另一个预先填充了所有24个时间段的表,并与之进行连接:
Interval_ID Interval
1 0000-0100
2 0100-0200
...
执行外部联接,任何没有数据的间隔都将在“读取”中显示为空。如果需要,将它们转换为零
这是一种相当常见的约会技巧,没有理由不能用间隔来完成。有时,为了解决这类计数问题,甚至可以方便地创建一个只包含1到1000之间所有整数的列表的表
-更新-
如果无法创建要联接的表,可以尝试联接到查询中创建的集合。语法如下所示:
date_tr timeofday reads
01/19/2014 0500 - 0600 12
01/19/2014 0600 - 0700 15
01/19/2014 0800 - 0900 22
...
select
intervals.interval,
mytable.*
from
mytable
right join (
select '0000-0100' as interval
union all
select '0100-0200' as interval
union all
...
select '2300-2400' as interval ) intervals
on
mytable.interval = intervals.interval
这是我脑子里想不出来的代码,但它应该能让你找到正确的方向。不是很优雅,但因为您只关心24个值,这也不算太糟糕。最简单的方法是创建另一个预先填充了所有24个时间段的表,并使用它进行连接:
Interval_ID Interval
1 0000-0100
2 0100-0200
...
执行外部联接,任何没有数据的间隔都将在“读取”中显示为空。如果需要,将它们转换为零
这是一种相当常见的约会技巧,没有理由不能用间隔来完成。有时,为了解决这类计数问题,甚至可以方便地创建一个只包含1到1000之间所有整数的列表的表
-更新-
如果无法创建要联接的表,可以尝试联接到查询中创建的集合。语法如下所示:
date_tr timeofday reads
01/19/2014 0500 - 0600 12
01/19/2014 0600 - 0700 15
01/19/2014 0800 - 0900 22
...
select
intervals.interval,
mytable.*
from
mytable
right join (
select '0000-0100' as interval
union all
select '0100-0200' as interval
union all
...
select '2300-2400' as interval ) intervals
on
mytable.interval = intervals.interval
这是我脑子里想不出来的代码,但它应该能让你找到正确的方向。不是很优雅,但因为您只关心24个值,这也不算太糟糕。最简单的方法是创建另一个预先填充了所有24个时间段的表,并使用它进行连接:
Interval_ID Interval
1 0000-0100
2 0100-0200
...
执行外部联接,任何没有数据的间隔都将在“读取”中显示为空。如果需要,将它们转换为零
这是一种相当常见的约会技巧,没有理由不能用间隔来完成。有时,为了解决这类计数问题,甚至可以方便地创建一个只包含1到1000之间所有整数的列表的表
-更新-
如果无法创建要联接的表,可以尝试联接到查询中创建的集合。语法如下所示:
date_tr timeofday reads
01/19/2014 0500 - 0600 12
01/19/2014 0600 - 0700 15
01/19/2014 0800 - 0900 22
...
select
intervals.interval,
mytable.*
from
mytable
right join (
select '0000-0100' as interval
union all
select '0100-0200' as interval
union all
...
select '2300-2400' as interval ) intervals
on
mytable.interval = intervals.interval
这是我脑子里想不出来的代码,但它应该能让你找到正确的方向。不是很优雅,但因为您只关心24个值,这也不算太糟糕。最简单的方法是创建另一个预先填充了所有24个时间段的表,并使用它进行连接:
Interval_ID Interval
1 0000-0100
2 0100-0200
...
执行外部联接,任何没有数据的间隔都将在“读取”中显示为空。如果需要,将它们转换为零
这是一种相当常见的约会技巧,没有理由不能用间隔来完成。有时,为了解决这类计数问题,甚至可以方便地创建一个只包含1到1000之间所有整数的列表的表
-更新-
如果无法创建要联接的表,可以尝试联接到查询中创建的集合。语法如下所示:
date_tr timeofday reads
01/19/2014 0500 - 0600 12
01/19/2014 0600 - 0700 15
01/19/2014 0800 - 0900 22
...
select
intervals.interval,
mytable.*
from
mytable
right join (
select '0000-0100' as interval
union all
select '0100-0200' as interval
union all
...
select '2300-2400' as interval ) intervals
on
mytable.interval = intervals.interval
这是我脑子里想不出来的代码,但它应该能让你找到正确的方向。虽然不优雅,但由于您只关心24个值,这也不算太糟糕。这里有一个2005年的友好解决方案
;WITH t AS
(
SELECT DISTINCT gi.placa, -- not sure that you really want distinct there
d = DATEADD(DAY, DATEDIFF(DAY,0,tr.inDate),0), h = DATEPART(HOUR, tr.inDate)
FROM dbo.RFIDTransaction AS tr
INNER JOIN dbo.RFIDGeneralInformation AS gi
ON tr.tag = gi.tag
WHERE tr.inDate >= DATEADD(DAY, -1, CURRENT_TIMESTAMP)
AND tr.inDate < CURRENT_TIMESTAMP
AND tr.removed = 0 AND gi.removed = 0
AND tr.inLoc = 'GATE IN'
),
h(h) AS
(
SELECT TOP (24) DATEADD(HOUR,-number,DATEADD(HOUR, DATEDIFF(HOUR,0,GETDATE()),0))
FROM master.dbo.spt_values WHERE [type] = N'P' AND number > 0
ORDER BY number
),
s AS
(
SELECT
dh = h.h,
d = CONVERT(CHAR(10), h.h, 101),
hs = CONVERT(CHAR(2), h.h, 108),
he = CONVERT(CHAR(2), DATEADD(HOUR, 1, h.h), 108),
c = COUNT(t.d)
FROM h LEFT OUTER JOIN t
ON DATEADD(HOUR, t.h, t.d) >= h.h
AND DATEADD(HOUR, t.h, t.d) < DATEADD(HOUR, 1, h.h)
GROUP BY h.h
)
SELECT
date_tr = d,
timeofday = RIGHT('0' + hs,2) + '00 - ' + RIGHT('0' + he,2) + '00',
reads = c
FROM s ORDER BY dh;
在2005年,你没有更多的工作要做,因为你不能利用
时间
。当我有更多的时间时,我将不得不重新讨论这个问题,我只是想表达一下让您开始的基本方法。这是一个2005年的友好解决方案
;WITH t AS
(
SELECT DISTINCT gi.placa, -- not sure that you really want distinct there
d = DATEADD(DAY, DATEDIFF(DAY,0,tr.inDate),0), h = DATEPART(HOUR, tr.inDate)
FROM dbo.RFIDTransaction AS tr
INNER JOIN dbo.RFIDGeneralInformation AS gi
ON tr.tag = gi.tag
WHERE tr.inDate >= DATEADD(DAY, -1, CURRENT_TIMESTAMP)
AND tr.inDate < CURRENT_TIMESTAMP
AND tr.removed = 0 AND gi.removed = 0
AND tr.inLoc = 'GATE IN'
),
h(h) AS
(
SELECT TOP (24) DATEADD(HOUR,-number,DATEADD(HOUR, DATEDIFF(HOUR,0,GETDATE()),0))
FROM master.dbo.spt_values WHERE [type] = N'P' AND number > 0
ORDER BY number
),
s AS
(
SELECT
dh = h.h,
d = CONVERT(CHAR(10), h.h, 101),
hs = CONVERT(CHAR(2), h.h, 108),
he = CONVERT(CHAR(2), DATEADD(HOUR, 1, h.h), 108),
c = COUNT(t.d)
FROM h LEFT OUTER JOIN t
ON DATEADD(HOUR, t.h, t.d) >= h.h
AND DATEADD(HOUR, t.h, t.d) < DATEADD(HOUR, 1, h.h)
GROUP BY h.h
)
SELECT
date_tr = d,
timeofday = RIGHT('0' + hs,2) + '00 - ' + RIGHT('0' + he,2) + '00',
reads = c
FROM s ORDER BY dh;
在2005年,你没有更多的工作要做,因为你不能利用
时间
。当我有更多的时间时,我将不得不重新讨论这个问题,我只是想表达一下让您开始的基本方法。这是一个2005年的友好解决方案
;WITH t AS
(
SELECT DISTINCT gi.placa, -- not sure that you really want distinct there
d = DATEADD(DAY, DATEDIFF(DAY,0,tr.inDate),0), h = DATEPART(HOUR, tr.inDate)
FROM dbo.RFIDTransaction AS tr
INNER JOIN dbo.RFIDGeneralInformation AS gi
ON tr.tag = gi.tag
WHERE tr.inDate >= DATEADD(DAY, -1, CURRENT_TIMESTAMP)
AND tr.inDate < CURRENT_TIMESTAMP
AND tr.removed = 0 AND gi.removed = 0
AND tr.inLoc = 'GATE IN'
),
h(h) AS
(
SELECT TOP (24) DATEADD(HOUR,-number,DATEADD(HOUR, DATEDIFF(HOUR,0,GETDATE()),0))
FROM master.dbo.spt_values WHERE [type] = N'P' AND number > 0
ORDER BY number
),
s AS
(
SELECT
dh = h.h,
d = CONVERT(CHAR(10), h.h, 101),
hs = CONVERT(CHAR(2), h.h, 108),
he = CONVERT(CHAR(2), DATEADD(HOUR, 1, h.h), 108),
c = COUNT(t.d)
FROM h LEFT OUTER JOIN t
ON DATEADD(HOUR, t.h, t.d) >= h.h
AND DATEADD(HOUR, t.h, t.d) < DATEADD(HOUR, 1, h.h)
GROUP BY h.h
)
SELECT
date_tr = d,
timeofday = RIGHT('0' + hs,2) + '00 - ' + RIGHT('0' + he,2) + '00',
reads = c
FROM s ORDER BY dh;
在2005年,你没有更多的工作要做,因为你不能利用
时间
。当我有更多的时间时,我将不得不重新讨论这个问题,我只是想表达一下让您开始的基本方法。这是一个2005年的友好解决方案
;WITH t AS
(
SELECT DISTINCT gi.placa, -- not sure that you really want distinct there
d = DATEADD(DAY, DATEDIFF(DAY,0,tr.inDate),0), h = DATEPART(HOUR, tr.inDate)
FROM dbo.RFIDTransaction AS tr
INNER JOIN dbo.RFIDGeneralInformation AS gi
ON tr.tag = gi.tag
WHERE tr.inDate >= DATEADD(DAY, -1, CURRENT_TIMESTAMP)
AND tr.inDate < CURRENT_TIMESTAMP
AND tr.removed = 0 AND gi.removed = 0
AND tr.inLoc = 'GATE IN'
),
h(h) AS
(
SELECT TOP (24) DATEADD(HOUR,-number,DATEADD(HOUR, DATEDIFF(HOUR,0,GETDATE()),0))
FROM master.dbo.spt_values WHERE [type] = N'P' AND number > 0
ORDER BY number
),
s AS
(
SELECT
dh = h.h,
d = CONVERT(CHAR(10), h.h, 101),
hs = CONVERT(CHAR(2), h.h, 108),
he = CONVERT(CHAR(2), DATEADD(HOUR, 1, h.h), 108),
c = COUNT(t.d)
FROM h LEFT OUTER JOIN t
ON DATEADD(HOUR, t.h, t.d) >= h.h
AND DATEADD(HOUR, t.h, t.d) < DATEADD(HOUR, 1, h.h)
GROUP BY h.h
)
SELECT
date_tr = d,
timeofday = RIGHT('0' + hs,2) + '00 - ' + RIGHT('0' + he,2) + '00',
reads = c
FROM s ORDER BY dh;
在2005年,你没有更多的工作要做,因为你不能利用
时间
。当我有更多的时间时,我将不得不重新讨论这个问题,只是想表达让您开始的基本方法。作为正确方向的一点,我倾向于使用一个基本表,它将提供适用日期/时间范围的列表,并将其用作主表,然后将其与可能不存在的结果左外连接。也就是说,请使用显式连接语法,除非您有充分的理由不这样做。这将使您或您的替代者更容易获得未来的支持作为正确方向的一点,我倾向于使用一个基表,它将提供适用日期/时间范围的列表,并将其用作主表,然后将其与可能不存在的结果左外连接。也就是说,请使用显式连接语法,除非您有充分的理由不这样做。这将使您或您的替代者更容易获得未来的支持作为正确方向的一点,我倾向于使用一个基表,它将提供适用日期/时间范围的列表,并将其用作主表,然后将其与可能不存在的结果左外连接。也就是说,请使用显式连接语法,除非您有充分的理由不这样做。它将使您或您的替代者更容易获得未来的支持