Tsql SQL合并开始日期和结束日期
我想合并一个日志事件中的多个开始日期和结束日期,以便一个日期有一行 输入表为:Tsql SQL合并开始日期和结束日期,tsql,date,merge,Tsql,Date,Merge,我想合并一个日志事件中的多个开始日期和结束日期,以便一个日期有一行 输入表为: Ord Desc2 Date_Time -------------------------- 0 Down 1/1/2014 ==> Not merged because no Up after 1 Down 1/2/2014 ==> Rows 1 and 2 should be merged 2 Up 1/3/20
Ord Desc2 Date_Time
--------------------------
0 Down 1/1/2014 ==> Not merged because no Up after
1 Down 1/2/2014 ==> Rows 1 and 2 should be merged
2 Up 1/3/2014
5 Down 1/4/2014 ==> Rows 5 and 12 should be merged
12 Up 1/6/2014
13 Up 1/7/2014 ==> Not merged because no Down before
所以我想要的结果是:
Ord DesactivationDateTime ActivationDateTime
----------------------------------------------------
0 1/1/2014
1 1/2/2014 1/3/2014
5 1/4/2014 1/6/2014
13 1/7/2014
我发现的SQL请求是这样的,但它只适用于上/下两个:
SELECT EventsDesactivation.Ord
, EventsDesactivation.Desc2
, EventsDesactivation.Date_Time AS DesactivationDateTime
, MIN(EventsActivation.Date_Time) AS ActivationDateTime
FROM Journal AS EventsDesactivation
LEFT OUTER JOIN Journal AS EventsActivation
ON EventsActivation.Module=EventsDesactivation.Module --This is one of common rows not displayed in this sample...
WHERE
(EventsDesactivation.Desc2 = 'Down')
AND (EventsActivation.Desc2 = 'Up')
AND (EventsActivation.Ord > EventsDesactivation.Ord)
GROUP BY EventsDesactivation.Ord, EventsDesactivation.Desc2, EventsDesactivation.Date_Time
如果你能帮我找到解决办法,我将不胜感激!
我的最后一个想法是做一个疯狂的结合所有的夫妇和单身者行与最后一组由
谢谢你的帮助
问候,,
François这与您的样本数据和预期结果相符,但我有一种烦人的感觉,我遗漏了一些边缘案例:
declare @t table (Ord int, Desc2 varchar(13),Date_Time date)
insert into @t(Ord,Desc2,Date_Time) values
(0 ,'Down','20140101'),
(1 ,'Down','20140102'),
(2 ,'Up','20140103'),
(5 ,'Down','20140104'),
(12 ,'Up','20140106'),
(13 ,'Up','20140107')
;With numbered as (
select Ord,Desc2,Date_Time,
ROW_NUMBER() OVER (ORDER BY Ord /* or date_time? */) as rn
from
@t
)
select
CASE WHEN n1.Desc2='Up' and n2.Desc2='Up' THEN n2.Ord ELSE n1.Ord END,
CASE WHEN n1.Desc2='Up' and n2.Desc2='Up' THEN NULL ELSE n1.Date_Time END,
CASE WHEN n1.Desc2='Down' and n2.Desc2='Down' THEN NULL ELSE n2.Date_Time END
from
numbered n1
full outer join
numbered n2
on
n1.rn = n2.rn - 1
where
not (n1.Desc2='Up' and n2.Desc2='Down')
基本上,我们将每一行与逻辑上位于其后的行连接起来。我们忽略上一行和下一行。然后我们只需要计算出它是向下,向上正常,向下,向下只报告第一行的值还是向上,向上只报告第二行的值
结果:
----------- ---------- ----------
0 2014-01-01 NULL
1 2014-01-02 2014-01-03
5 2014-01-04 2014-01-06
13 NULL 2014-01-07
我已经将您的想法应用到我的现实世界中,它在存储过程中工作得非常完美。谢谢你! 但是我的SQL客户端不支持存储过程。。。我真丢脸 所以我决定用pamareters创建一个表函数来调用这个SQL代码 不幸的是,在我的使用中,我没有找到使用名为Event的中间编号表的方法。。。 我在网上犯了以下错误;活动包括: ==>函数中包含的select语句无法向客户端返回数据 下面是我完成的函数代码:
CREATE FUNCTION fnSensorsDesactivations
(
@dateStartInString nvarchar(50) = '',
@dateEndInString nvarchar(50) = '',
@Unit nvarchar(50) = null,
@HoursToAddFromGMT int = -2,
@DesactivationEventsFilter nvarchar(50) = 'Validation et Désactivation%',
@BeforeDesactivationComment nvarchar(50) = 'Validation et Désactivation Capteur par ',
@AfterDesactivationComment nvarchar(50) = '. Commentaire : ',
@ActivationEventsFilter nvarchar(50) = 'Activation Capteur par%',
@BeforeActivationUsername nvarchar(50) = 'Activation Capteur par '
)
RETURNS @TableTempToReturn TABLE
(
-- Add the column definitions for the TABLE variable here
--Ord int,
Unit nvarchar(50),
Module nvarchar(255),
Module_Description nvarchar(255),
DésactivationQui nvarchar(255),
DésactivationDateTime nvarchar(255),
DésactivationMessage nvarchar(255),
ActivationQui nvarchar(255),
ActivationDateTime nvarchar(255)
)
AS
BEGIN
DECLARE @ExcludeOrds AS nvarchar(255) -- Must be comma separated and also at first and last character
DECLARE @dateStart AS datetime -- to cast datetime from string because Dream Report is not able to pass parameters with formulas
DECLARE @dateEnd AS datetime -- to cast datetime from string because Dream Report is not able to pass parameters with formulas
SET @ExcludeOrds=',,,,,,,,,'
IF @dateStartInString='' OR @dateEndInString=''
BEGIN
--Init dates from yesterday to today if they are null
SET @dateEnd=GETDATE()
SET @dateStart=DATEADD(year, -1, @DateEnd)
END
ELSE
BEGIN
--Convert datetime from string to datetime format + hours from GMT to follow local datetime settings
SET @dateEnd=DATEADD(hour, @HoursToAddFromGMT, CONVERT(datetime, @dateEndInString, 121))
SET @dateStart=DATEADD(hour, @HoursToAddFromGMT, CONVERT(datetime, @dateStartInString, 121))
END
IF @Unit IS NULL SET @Unit='WIP-BC2'
--Calculate positions/orders of differents Activation and desactivation events
;WITH Events AS -- Here is my SQL error: select statements included whithin a function cannot return a data to a client.
(
SELECT Ord, Unit, Module, Module_Description, Desc2, Date_Time,
ROW_NUMBER() OVER (ORDER BY Unit, Module, Ord) AS rn
FROM
EJournal.dbo.Journal
WHERE
Date_Time <= @dateEnd
AND Unit = @Unit
AND (Desc2 like @DesactivationEventsFilter
OR Desc2 like @ActivationEventsFilter)
--AND (Date_Time like @ActivationEventsFilter and Date_Time<=@dateStart)
AND CHARINDEX(CAST(Ord AS nvarchar), @ExcludeOrds,1)=0
)
--Depending on desactivation and activation orders, select good Events in Activation/descativation columns
SELECT
--n1.Ord,n2.Ord, n1.Desc2, n2.Desc2,
n1.Module
, n1.Module_Description
, CASE
WHEN n1.Desc2 like @ActivationEventsFilter AND n2.Desc2 like @ActivationEventsFilter
THEN ''
WHEN n1.Desc2 like @DesactivationEventsFilter AND (n2.Desc2 like @ActivationEventsFilter OR n2.Ord IS NULL)
THEN ISNULL(LEFT(SUBSTRING(n1.Desc2, LEN(@BeforeDesactivationComment)+2, 255 )
, CHARINDEX(@AfterDesactivationComment, SUBSTRING(n1.Desc2, LEN(@BeforeDesactivationComment)+2, 255)) - 1), '')
WHEN n1.Desc2 like @DesactivationEventsFilter AND (n2.Desc2 like @DesactivationEventsFilter OR n2.Ord IS NULL)
THEN ISNULL(LEFT(SUBSTRING(n1.Desc2, LEN(@BeforeDesactivationComment)+2, 255 ), '')
, CHARINDEX(@AfterDesactivationComment, SUBSTRING(n1.Desc2, LEN(@BeforeDesactivationComment)+2, 255)) - 1)
ELSE ''
END AS DésactivationQui
, CASE
WHEN n1.Desc2 like @ActivationEventsFilter AND n2.Desc2 like @ActivationEventsFilter
THEN ''
WHEN n1.Desc2 like @DesactivationEventsFilter AND (n2.Desc2 like @ActivationEventsFilter OR n2.Ord IS NULL)
THEN ISNULL(CONVERT(nvarchar, n1.Date_Time, 121), '')
WHEN n1.Desc2 like @DesactivationEventsFilter AND (n2.Desc2 like @DesactivationEventsFilter OR n2.Ord IS NULL)
THEN ISNULL(CONVERT(nvarchar, n1.Date_Time, 121), '')
ELSE ''
END AS DésactivationDateTime
, CASE
WHEN n1.Desc2 like @ActivationEventsFilter AND n2.Desc2 like @ActivationEventsFilter
THEN ''
WHEN n1.Desc2 like @DesactivationEventsFilter AND (n2.Desc2 like @ActivationEventsFilter OR n2.Ord IS NULL)
THEN ISNULL(SUBSTRING(n1.Desc2, CHARINDEX(@AfterDesactivationComment, n1.Desc2)+LEN(@AfterDesactivationComment), 255 ) , '')
WHEN n1.Desc2 like @DesactivationEventsFilter AND (n2.Desc2 like @DesactivationEventsFilter OR n2.Ord IS NULL)
THEN ISNULL(SUBSTRING(n1.Desc2, CHARINDEX(@AfterDesactivationComment, n1.Desc2)+LEN(@AfterDesactivationComment), 255 ) , '')
ELSE ''
END AS DésactivationMessage
, CASE
WHEN n1.Desc2 like @ActivationEventsFilter AND n2.Desc2 like @ActivationEventsFilter
THEN ISNULL(SUBSTRING(n2.Desc2, LEN(@BeforeActivationUsername)+2, 255 ),'')
WHEN (n1.Desc2 like @DesactivationEventsFilter OR n1.Ord IS NULL) AND n2.Desc2 like @ActivationEventsFilter
THEN ISNULL(SUBSTRING(n2.Desc2, LEN(@BeforeActivationUsername)+2, 255 ), '')
--WHEN n1.Desc2 like @DesactivationEventsFilter AND n2.Desc2 like @DesactivationEventsFilter THEN ''
-- THEN ''
ELSE ''
END AS ActivationQui
, CASE
WHEN n1.Desc2 like @ActivationEventsFilter AND n2.Desc2 like @ActivationEventsFilter
THEN ISNULL(CONVERT(nvarchar, n2.Date_Time, 121),'')
WHEN (n1.Desc2 like @DesactivationEventsFilter OR n1.Ord IS NULL) AND n2.Desc2 like @ActivationEventsFilter
THEN ISNULL(CONVERT(nvarchar, n2.Date_Time, 121),'')
--WHEN n1.Desc2 like @DesactivationEventsFilter AND n2.Desc2 like @DesactivationEventsFilter
-- THEN ''
ELSE ''
END AS ActivationDateTime
FROM
Events n1
FULL OUTER JOIN
Events n2
ON n1.rn = n2.rn - 1
AND n1.Unit=n2.Unit
AND n1.Module=n2.Module
WHERE NOT (n1.Desc2 like @ActivationEventsFilter AND n2.Desc2 like @DesactivationEventsFilter)
AND n1.Desc2 like @DesactivationEventsFilter
AND n1.Date_Time <= @dateEnd
--AND n2.Date_Time <= @dateEnd
AND (n2.Ord IS NULL OR n2.Date_Time>=@dateStart)
RETURN
结束
你能想出一个神奇的解决办法吗
再次感谢你的帮助!
弗朗索瓦太棒了!谢谢你的回答!您是否有一个解决方案,只使用一个SELECT和行号?我不确定我的最终SQL客户端是否允许这样的请求。。。不管怎样,听起来不错