我有两对DATE的表。我想根据这些日期的时间来订购结果。每行至少一对日期(当一行有两个区间时:start2> start1,end2> end1和start2> = end1),如下所示:
| start1 | end1 | start2 | end2
row 1 | 4:00 | 5:00 | 5:00 | 6:00
row 2 | 4:30 | 5:00 | NULL | NULL
row 3 | NULL | NULL | 5:30 | 6:00
row 4 | 5:00 | 6:00 | 6:00 | 7:00
当两行都有两对时,应该用start1进行比较。
当一行只有pair1而另一行只有pair2时,应将start1与start2进行比较
当一行只有一对(任何)而另一对都有两对时,它们应该由第一行具有的对(start1到start1或start2到start2)进行比较。例如:如果第一行只有start2和end2,第二行有start1,end1,start2和end2,那么这两行应该只用start2进行比较(应忽略第二行的start1)
< / LI>我该如何实现?
修改
我可以在C#中轻松完成,但我需要在数据库中执行此操作。下面的代码如何在C#中起作用:
static void Main(string[] args)
{
...
intervals.Sort(new IntervalComparer());
}
public class IntervalComparer : IComparer<Interval>
{
public int Compare(Interval quadro1, Interval quadro2)
{
int result = 0;
if (quadro1.start1 != null && quadro2.start1 != null)
result = quadro1.start1.Value.CompareTo(quadro2.start1.Value);
else if (quadro1.start2 != null && quadro2.start2 != null)
result = quadro1.start2.Value.CompareTo(quadro2.start2.Value);
else if (quadro1.start1 != null)
result = quadro1.start1.Value.CompareTo(quadro2.start2.Value);
else
result = quadro1.start2.Value.CompareTo(quadro2.start1.Value);
return result;
}
}
答案 0 :(得分:1)
你的逻辑存在缺陷。请考虑以下示例:
| start1 | start2
a | 4:00 | 7:00
b | 5:00 | NULL
c | NULL | 6:00
对于该数据,使用您的逻辑将会是以下情况:
a < b (a.start1 = 4:00 < b.start1 = 5:00)
b < c (b.start1 = 5:00 < c.start2 = 6:00)
c < a (c.start2 = 6:00 < a.start2 = 7:00)
因此a < b < c < a
也是&#34; true&#34;。但是如果你想要一个有意义的命令,那么<
oprator应该是可传递的。这意味着如果a < b
为TRUE且b < c
为TRUE,则a < c
也应为TRUE。但事实并非如此。
因此,您可以将这三行命名为[a, b, c]
或[b, c, a]
或[c, a, b]
。对我而言,它没有意义。
如果您需要SQL解决方案,则应重新定义逻辑。我建议使用估计的(平均)差异(AVG(start2 - start1)
)来填充NULL。在我的例子中,平均差异是3小时。因此,b.start2
将替换为b.start1 + 3 hours = 8:00
。 c.start1
将替换为c.start2 - 3 hours = 3:00
。您现在可以按估计值排序。
MySQL示例:
select t.*
, d.avg_diff
, coalesce(time_to_sec(t.start1), time_to_sec(t.start2) - d.avg_diff) as estimated1
, coalesce(time_to_sec(t.start2), time_to_sec(t.start1) + d.avg_diff) as estimated2
from my_table t
cross join (
select avg(time_to_sec(start2) - time_to_sec(start1))
as avg_diff
from my_table
) d
order by estimated1, estimated2;
您当然可以在ORDER BY子句中使用估算表达式:
select t.*
from my_table t
cross join (
select avg(time_to_sec(start2) - time_to_sec(start1))
as avg_diff
from my_table
) d
order by
coalesce(time_to_sec(t.start1), time_to_sec(t.start2) - d.avg_diff),
coalesce(time_to_sec(t.start2), time_to_sec(t.start1) + d.avg_diff);
演示:http://rextester.com/HHLT51865
使用原始数据进行演示:http://rextester.com/AMJIDT94457
答案 1 :(得分:0)
尝试使用IF function,它应该是以下内容:
SELECT if(start1 not is null, TIME(start1), TIME(start2) ) AS sortable_value
FROM your_table ORDER by sortable_value
您的整个逻辑可以像上面的查询一样进行简化。如果start1不为null,则基本上减少为,然后按时间排序,否则按start2的时间排序。
如果我误解了某些内容,那么你可以添加另一个IF
而不是TIME(start1)(相当于then
分支)或代替TIME(start2)(相当于{{1 }})。