在我的SQL查询中使用数据值的子字符串

时间:2010-12-22 16:11:51

标签: sql sql-server function aggregate substring

我的数据库中的数据如下所示:

Date (DateTime)        Type (varchar)  Data (varchar)
2010/12/22 6:00        Geofence        Area 1,1
2010/12/22 7:00        Geofence        Area 1,0
2010/12/22 7:30        Geofence        Area 2,1
2010/12/22 7:45        Geofence        Area 2,0
2010/12/22 8:00        Geofence        Area 3,1

如您所见,对于地理围栏数据类型,数据使用逗号分割,前半部分包含地理围栏的名称,后半部分表示该点是否已进入或退出地理围栏。

我要做的是获取每个区域的所有最新Geofence类型条目的列表。我的理想输出看起来像这样:

Date                   Type       Data
2010/12/22 7:00        Geofence   Area 1,0
2010/12/22 7:45        Geofence   Area 2,0
2010/12/22 8:00        Geofence   Area 3,1

我的假设SQL语句看起来像这样

SELECT MAX(Date) AS LatestDate, Data
FROM MyTable
WHERE Type = 'Geofence'
GROUP BY FirstHalfOf(Data)

是否可以保持相同的表结构?

我正在使用MS SQL Server 2008

由于

P.S。根据要求,这里有一些SQL代码来创建表并用示例数据填充它:

CREATE TABLE TestData (
    id int PRIMARY KEY IDENTITY,
    Date datetime NOT NULL,
    Type varchar(50) NOT NULL,
    Data varchar(max) NULL)

INSERT INTO TestData (Date, Type, Data)
VALUES('2010/12/22 6:00', 'Geofence', 'Area 1,1')
INSERT INTO TestData (Date, Type, Data)
VALUES('2010/12/22 7:00', 'Geofence', 'Area 1,0')
INSERT INTO TestData (Date, Type, Data)
VALUES('2010/12/22 7:30', 'Geofence', 'Area 2,1')
INSERT INTO TestData (Date, Type, Data)
VALUES('2010/12/22 7:45', 'Geofence', 'Area 2,0')
INSERT INTO TestData (Date, Type, Data)
VALUES('2010/12/22 8:00', 'Geofence', 'Area 3,1')

2 个答案:

答案 0 :(得分:1)

这适用于MySQL,子字符串函数因平台而异:

select m.Date, m.Type, m.Data
from MyTable m
inner join (
    SELECT SUBSTRING_INDEX(Data, ',', 1) as LeftData, 
        MAX(Date) AS LatestDate
    FROM MyTable 
    WHERE Type = 'Geofence' 
    GROUP BY SUBSTRING_INDEX(Data, ',', 1)
) mm on m.Date = mm.LatestDate
    and SUBSTRING_INDEX(m.Data, ',', 1) = mm.LeftData

答案 1 :(得分:1)

以下是MS SQL Server的解决方案

;WITH cte
          AS (
              SELECT    id,
                        Date,
                        Type,
                        Data,
                        SUBSTRING(Data, 1, CASE WHEN CHARINDEX(',', Data) = 0
                                           THEN LEN(Data)
                                           ELSE (CHARINDEX(',', Data) - 1)
                                           END) AS k
              FROM      TestData
             ),
        counts
          AS (
              SELECT    *,
                        duplicateCount = ROW_NUMBER() 
                        OVER (PARTITION BY k ORDER BY k, date desc)
              FROM      cte
             )
    SELECT  *
    FROM    counts
    WHERE   duplicateCount = 1