选择最近的日期

时间:2018-08-31 04:53:58

标签: sql sql-server sql-server-2012

我的数据结构如下:

ID | Enrolment_Date | Appointment1_Date | Appointment2_Date | .... | Appointment150_Date |
112  01/01/2015       01/02/2015          01/03/2018                 01/08/2018    
113  01/06/2018       01/07/2018          NULL                       NULL
114  01/04/2018       01/05/2018          01/06/2018                 NULL

我需要一个新的变量,用于计算enrollment_date和最近的约会之间的月数。面临的挑战是所有个人都有不同数量的约会。

更新:我同意以下意见:表设计不佳,需要重新格式化。提议的解决方案可以包括关于如何转换表格的建议代码吗?

4 个答案:

答案 0 :(得分:0)

您将需要重组数据,因为给定的结构数据库设计不佳。
创建两个单独的表-一个称为用户,另一个称为约会。 users表包含用户ID,注册日期和任何其他特定的用户信息。约会表中的每一行都包含用户的唯一ID和特定的约会日期。这样构造表将使编写查询以使自上次约会以来的天数/月数变得更容易。
例如:

Users Table: 

ID, Enrollment_Date
1, 2018-01-01 
2, 2018-03-02
3, 2018-05-02

Appointments Table: 

ID, Appointment_Date
1, 2018-01-02
1, 2018-02-02
1, 2018-02-10
2, 2018-05-01

然后,您将可以编写查询以将两个表连接在一起,并计算注册日期和约会日期的最小值之间的差。

答案 1 :(得分:0)

最好创建两个表。

注册表(dbo.Enrollments)

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    if info.count > 0 {
        collectionView.scrollToItem(at: IndexPath(item:info.count - 1, section: 0), at: .top, animated: false)
    }
}

约会表(dbo。约会)

ID   |   EnrolmentDate

1    | 2018-08-30

2    | 2018-08-31

然后您可以尝试这样的事情。

如果您希望从注册日期到最终任命日期的月份数,请使​​用以下查询。

ID | EnrolmentID | AppointmentDate
1  | 1           | 2018-09-02
2  | 1           | 2018-09-03 
3  | 2           | 2018-09-01
4  | 2           | 2018-09-03

并且,如果您希望从注册日期到最接近的约会日期的月份数,请使​​用以下查询。

SELECT E.ID, E.EnrolmentDate, A.NoOfMonths
FROM dbo.Enrolments E
OUTER APPLY
(
  SELECT DATEDIFF(mm, E.EnrolmentDate, MAX(A.AppointmentDate)) AS NoOfMonths
  FROM dbo.Appointments A
  WHERE A.EnrolmentId = E.ID
) A

sqlfiddle上尝试

答案 2 :(得分:0)

由于OP当前停留在这种不良设计中,因此我将提出一个临时解决方案。正如其他人所建议的,您实际上必须在这里更改结构。目前,这已足够:

SELECT '['+ NAME + '],' FROM sys.columns WHERE OBJECT_ID = OBJECT_ID ('TableA') -- find all columns, last one probably max appointment date

SELECT ID, 
      Enrolment_Date, 
      CASE WHEN Appointment150_Date IS NOT NULL THEN DATEDIFF (MONTH, Enrolment_Date, Appointment150_Date)
           WHEN Appointment149_Date IS NOT NULL THEN DATEDIFF (MONTH, Enrolment_Date, Appointment149_Date)
           WHEN Appointment148_Date IS NOT NULL THEN DATEDIFF (MONTH, Enrolment_Date, Appointment148_Date)
           WHEN Appointment147_Date IS NOT NULL THEN DATEDIFF (MONTH, Enrolment_Date, Appointment147_Date)
           WHEN Appointment146_Date IS NOT NULL THEN DATEDIFF (MONTH, Enrolment_Date, Appointment146_Date)
           WHEN Appointment145_Date IS NOT NULL THEN DATEDIFF (MONTH, Enrolment_Date, Appointment145_Date)
           WHEN Appointment144_Date IS NOT NULL THEN DATEDIFF (MONTH, Enrolment_Date, Appointment144_Date) -- and so on
      END AS NumberOfMonths
 FROM TableA

这是一个非常丑陋的临时解决方案,应该这样考虑。

答案 3 :(得分:0)

您有一个糟糕的数据结构,正如其他人指出的那样。您实际上是一张桌子,每个约会一行。毕竟,第150次约会后会发生什么?

select t.id, t.Enrolment_Date,
       datediff(month, t.Enrolment_Date, m.max_Appointment_Date) as months_diff
from t cross apply
     (select max(Appointment_Date) as max_Appointment_Date
      from (values (Appointment1_Date),
                   (Appointment2_Date),
                   . . .
                   (Appointment150_Date)
           ) v(Appointment_Date)
     ) m;