SQL仅当COMPLETE字段为0时才查找最新记录

时间:2017-09-12 11:34:46

标签: sql sql-server-2012

我有一张表,其中包含用户提交的多条记录。在每个记录中都有一个名为COMPLETE的字段,用于指示记录是否完​​全完成。

我需要一种方法来获取用户的最新记录,其中COMPLETE为0,LOCATION,DATE是相同的,并且在COMPLETE为1的情况下不存在其他记录。在每个记录中还有其他字段,如Type,AMOUNT,Total等等。即使USER,LOCATION和DATE相同,它们也可能不同。

有一个SUB_DATE字段和ID字段,表示提交的日期和自动递增的ID号。这是表格:

ID  NAME  LOCATION  DATE       COMPLETE  SUB_DATE   TYPE1  AMOUNT1  TYPE2  AMOUNT2  TOTAL
1   user1   loc1    2017-09-15    1      2017-09-10  Food   12.25   Hotel  65.54   77.79
2   user1   loc1    2017-09-15    0      2017-09-11  Food   12.25   NULL      0   12.25
3   user1   loc2    2017-08-13    0      2017-09-05  Flight 140     Food      5   145.00
4   user1   loc2    2017-08-13    0      2017-09-10  Flight 140     NULL      0   140
5   user1   loc3    2017-07-14    0      2017-07-15  Taxi   25      NULL      0   25
6   user1   loc3    2017-08-25    1      2017-08-26  Food   45      NULL      0   45

我想要检索的结果是ID 4,因为SUB_DATE后面是ID 3.它具有相同的名称,位置和日期信息,并且没有带有1值的COMPLETE。

我还想检索ID 5,因为它是用户,位置,日期和完成的最新记录是0.

如果你能解释一下你的答案,帮助我理解解决方案中发生的事情,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

不确定我是否完全理解但是试试这个

SELECT  *
FROM    (
            SELECT *,
                    MAX(CONVERT(INT,COMPLETE)) OVER (PARTITION BY NAME,LOCATION,DATE) AS CompleteForNameLocationAndDate,
                    MAX(SUB_DATE) OVER (PARTITION BY NAME, LOCATION, DATE) AS LastSubDate
            FROM    your_table t
        ) a
WHERE   CompleteForNameLocationAndDate = 0 AND
        SUB_DATE = LastSubDate

所以我们在这里做了什么:

首先,如果您只在Management Studio中运行内部查询,您将看到它的作用:

第一个max函数将按照每个唯一的Name,Location,Date设置对表中的数据进行分区。 对于您的数据,ID 1& 2是第一个分区,3& 4是第二个分区,5是第3个分区,6是第4个分区。 因此,对于每个分区,它将在完整列中获得最大值。因此,任何具有1作为其最大值的分区都已完成。

另请注意,转换功能。这是因为COMPLETE的数据类型为BIT(1或0),并且max函数不适用于该数据类型。因此我们转换为INT。如果您的COMPLETE列是INT类型,则可以进行转换。

第二个max函数再次按唯一名称,位置和日期进行分区,但这次我们得到max_sub日期,它给出了名称,位置,日期的最新记录的日期

因此我们将该查询添加到派生表中,为简单起见,我们将其称为。我们需要这样做,因为SQL Server不允许在查询的WHERE子句中使用窗口函数。窗口函数是我们使用OVER关键字的函数。在理想的世界中,SQL会让我们做到

SELECT *,
       MAX(CONVERT(INT,COMPLETE)) OVER (PARTITION BY NAME,LOCATION,DATE) AS CompleteForNameLocationAndDate,
       MAX(SUB_DATE) OVER (PARTITION BY NAME, LOCATION, DATE) AS LastSubDate
FROM   your)table t
WHERE   MAX(CONVERT(INT,COMPLETE)) OVER (PARTITION BY NAME,LOCATION,DATE) = 0 AND
        SUB_DATE = MAX(SUB_DATE) OVER (PARTITION BY NAME, LOCATION, DATE)

但它不允许它,所以我们必须使用派生表。

那么我们基本上从派生表Where

中选择所有内容
CompleteForNameLocationAndDate = 0

哪些是名称,位置,日期分区没有标记为完整的记录。

然后我们进一步过滤,只询问每个分区的最新记录

SUB_DATE = LastSubDate

希望有道理,不确定你需要什么程度的细节?

作为一方,我会考虑重组您的表格(除非您已经简化以更好地解释此问题),如下所示:

(假设您的示例中的表格称为预订)

tblBooking
BookingID
PersonID
LocationID
Date
Complete
SubDate

tblPerson
PersonID
PersonName

tblLocation
LocationID
LocationName

tblType
TypeID
TypeName

tblBookingType
BookingTypeID
BookingID
TypeID
Amount

这样,如果您想在预订信息中添加Type3或Type4,则无需更改表格布局