我希望在Time Period Library for .NET中实现类似的功能,但在SQL中。
首先,我有一个包含开始日期和结束日期的多行的表格,我希望将它们合并在一起,如下所示:
然后有了这个结果而另一个来自另一个表,我想找出他们两个之间的交集,就像这样,但只有2个输入(找到两者中存在的时期):
一旦我有了交叉点就是总结它的时间。
这里我提供了一个带有预期输出的SQL小提琴,其中有一个例子:
答案 0 :(得分:1)
样本数据准备
<div id="15175860223750456"><script type="text/JavaScript" src="https://www.aparat.com/embed/xom4D?data[rnddiv]=15175860223750456&data[responsive]=yes"></script></div>
查询:
CREATE TABLE TableToCombine
([IdDoc] int IDENTITY(1,1), [IdEmployee] int, [StartDate] datetime, [EndDate] datetime)
;
INSERT INTO TableToCombine
(IdEmployee, StartDate, EndDate)
VALUES
(1, '2018-01-01 06:00:00', '2018-01-01 14:00:00'),
(2, '2018-01-01 11:00:00', '2018-01-01 19:00:00'),
(3, '2018-01-01 20:00:00', '2018-01-02 03:00:00'),
(1, '2018-01-02 06:00:00', '2018-01-02 14:00:00'),
(2, '2018-01-02 11:00:00', '2018-01-02 19:00:00')
;
CREATE TABLE TableToIntersect
([IdDoc] int IDENTITY(1,1), [OrderId] int, [StartDate] datetime, [EndDate] datetime)
;
INSERT INTO TableToIntersect
(OrderId, StartDate, EndDate)
VALUES
(1, '2018-01-01 09:00:00', '2018-01-02 12:00:00')
;
相交时间间隔在CTE中组合。然后与您的intersectTable一起查找重叠时段。如果with ExpectedCombineOutput as (
select
grp, StartDate = min(StartDate), EndDate = max(EndDate)
from (
select
*, sum(iif(cd between StartDate and EndDate, 0, 1))over(order by StartDate) grp
from (
select
*, lag(EndDate) over (order by IdDoc) cd
from
TableToCombine
) t
) t
group by grp
)
select
a.grp, StartDate = iif(a.StartDate < b.StartDate, b.StartDate, a.StartDate)
, EndDate = iif(a.EndDate < b.EndDate, a.EndDate, b.EndDate)
from
ExpectedCombineOutput a
join TableToIntersect b on a.StartDate <= b.EndDate and a.EndDate >= b.StartDate
答案 1 :(得分:0)
PinX0,我不确定我是否完全理解你的问题/要求。 以下查询为您提供ExpectedIntersectOutput的结果: -
public static ColumnInfo[] GetColumnsInfo(Type linqTableClass)
{
// Just looking in the loop to see if I missed something.
foreach (var fld in linqTableClass.GetProperties())
{
foreach (var attr in fld.CustomAttributes)
{
foreach (var arg in attr.NamedArguments)
{
if (arg.MemberName == "Name")
Debug.WriteLine(arg.MemberName);
Debug.WriteLine("{0}", arg.MemberName);
}
}
}
var columnInfoQuery =
from field in linqTableClass.GetProperties()
from attribute in field.CustomAttributes
from namedArgument in attribute.NamedArguments
where namedArgument.MemberName == "DbType"
select new ColumnInfo
{
//ColumnName = field.Name,
ColumnName = namedArgument.MemberName,
DatabaseType = namedArgument.TypedValue.Value.ToString(),
};
return columnInfoQuery.ToArray();
}
答案 2 :(得分:0)
这是MySQL中的一个有效示例。我为此使用了一个简单的视图。
让我们考虑与客户和员工的适应性。您需要知道当员工在场时客户花费了多少小时。
首先让您准备一个测试表:
CREATE TABLE Customer
(id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
customerId int NOT NULL,
arrival datetime,
leaving datetime);
INSERT INTO Customer
(customerId, arrival, leaving)
VALUES
(1, '2018-01-01 06:00:00', '2018-01-01 14:00:00'),
(2, '2018-01-01 11:00:00', '2018-01-01 19:00:00'),
(3, '2018-01-01 20:00:00', '2018-01-02 03:00:00'),
(1, '2018-01-02 06:00:00', '2018-01-02 14:00:00'),
(2, '2018-01-02 11:00:00', '2018-01-02 19:00:00')
;
CREATE TABLE Employee
(id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
employeeId int NOT NULL,
arrival datetime,
leaving datetime)
;
INSERT INTO Employee
(employeeId, arrival, leaving)
VALUES
(1, '2018-01-01 09:00:00', '2018-01-01 12:00:00',),
(2, '2018-01-01 11:30:00', '2018-01-01 20:00:00')
;
拥有表格后,让您创建带有时间交叉点的视图:
CREATE OR REPLACE VIEW intersectionTimeView AS select e.employeeId,
c.customerId,
IF(c.arrival>e.arrival, c.arrival, e.arrival) AS arrivalMax,
IF(c.leaving>e.leaving, e.leaving, c.leaving) AS leavingMin
FROM Customer c, Employee e
WHERE TIMEDIFF(c.arrival,e.leaving)<=0
AND TIMEDIFF(c.leaving,e.arrival)>=0
最后,您可以轻松获得小时数:
SELECT employeeId, SUM( timestampdiff(minute,arrivalMax,leavingMin)/60) as summ
FROM intersectionTimeView WHERE employeeId=2
GROUP BY employeeId