查询以序列化数据

时间:2013-02-17 22:44:51

标签: sql postgresql postgresql-9.2

我有两张桌子:

Routes

ID   Description
1    street1
2    street2
3    street3
4    street4
5    street5

Segments 

ID  RouteID, Progres, LabelStart, LabelEnd
1   1        5            1 A        21 B
2   1        10           2 A        10 
3   2        15           3          25 
4   2        15           2          20
5   3        20           1          11 
6   3        22           4          10
7   4        30           5          11 
8   4        31           2          12

我需要一个包含这些规则的序列:

  1. 表必须由Progress ASC订购
  2. 定义列类型,如果LabelStart和LabelEnd为Odd,则取O,如果是偶数则为E.
  3. 如果两个路由具有相同的进度,则行合并在一个路径中 LabelStart是最小的(在LabelStart Odd和LabelStart之中) 和LabelEnd是Max,在这种情况下Type取值A(All)
  4. 根据结果上面的示例数据应为

    Sequence  
    ID  RouteID, Progres, LabelStart, LabelEnd  Type
    1   1        5            1 A        21 B    O
    2   1        10           2 A        10      E 
    4   2        15           2          25      A
    5   3        20           1          11      O
    6   3        22           4          10      E
    7   4        30           5          11      O
    8   4        31           2          12      E
    

    适用于Postgres 9.2

1 个答案:

答案 0 :(得分:1)

这是一个有趣的查询,因为你的LabelStart和LabelEnd字段中有字母。我使用REGEX_REPLACE删除了那些。然后我使用CTE来获取具有多个routeid和进度行的记录。

我认为应该这样做:

WITH CTE AS (
  SELECT 
    RouteId, Progress
  FROM Sequence
  GROUP BY RouteId, Progress
  HAVING COUNT(DISTINCT Id) > 1
  )
SELECT MAX(S.ID) Id,
  T.RouteId,
  T.Progress,
  MIN(regexp_replace(LabelStart, '[^0-9]', '', 'g')) LabelStart,
  MAX(regexp_replace(LabelStart, '[^0-9]', '', 'g')) LabelEnd,
  'A' as Type
FROM Sequence S 
  INNER JOIN CTE T ON S.RouteId = T.RouteId AND S.Progress = T.Progress
GROUP BY T.RouteId, T.Progress
UNION 
SELECT S.Id,
  S.RouteId,
  S.Progress,
  S.LabelStart,
  S.LabelEnd,
  CASE 
    WHEN CAST(regexp_replace(LabelStart, '[^0-9]', '', 'g') as int) % 2 = 0 
    THEN 'E' 
    ELSE 'O' 
  END  
FROM Sequence S 
  LEFT JOIN  CTE T ON S.RouteId = T.RouteId AND S.Progress = T.Progress
WHERE T.RouteId IS NULL
ORDER BY Progress ASC

还有一些示例Fiddle