比较两组SQL“GROUP BY”结果

时间:2012-11-16 15:36:44

标签: sql tsql

这是我的表:

ROUTES = the route ID
STATIONS = the station ID
STOPS? = if the train stops at this station then is equal to 1 otherwise 0

-------------------------
ROUTES STATIONS  STOPS?
-------------------------
R1    S1    1
R1    S2    0
R1    S3    1
R1    S4    0
R1    S5    1
R2    S1    1
R2    S2    1
R2    S3    1
R2    S4    0
R2    S5    1
R3    S1    1
R3    S2    0
R3    S4    1
R3    S5    0
R3    S6    1
R3    S7    1
R4    S1    1
R4    S2    1
R4    S3    0
R4    S4    1
R5    S2    1
R5    S3    0
R5    S4    1

我想要做的是找出哪些路线经过相同的车站,但没有相同的车站。

例如: 我们看到了

Route R1 passes through stations S1->S2->S3->S4->S5 
Route R2 passes through stations S1->S2->S3->S4->S5 

但它们有不同的停止点,因此结果应为:

R1 
R2

我想先将所有路线分组,并将属于该组的STATIONS与其他所有路线进行比较,并检查它们是否至少有一个不同的停靠点。

6 个答案:

答案 0 :(得分:0)

以下查询将返回其中一列列车未停止的路线和车站http://sqlfiddle.com/#!3/f4c5f/8

  SELECT DISTINCT
    tblRoutes.ROUTES
   ,tblRoutesCross.ROUTES CrossingRoute
   ,tblRoutes.STATIONS
  FROM
    tblRoutes
  INNER JOIN
    tblRoutes tblRoutesCross
  ON
    tblRoutesCross.STATIONS = tblRoutes.STATIONS
  AND
    tblRoutes.ROUTES < tblRoutesCross.ROUTES
  AND
    (
       tblRoutesCross.STOPS = 0 
      OR
       tblRoutes.STOPS = 0 
    )

以下查询将仅返回过境路线:

 SELECT DISTINCT
    tblRoutes.ROUTES
   ,tblRoutesCross.ROUTES CrossingRoute
   --,tblRoutes.STATIONS
  FROM
    tblRoutes
  INNER JOIN
    tblRoutes tblRoutesCross
  ON
    tblRoutesCross.STATIONS = tblRoutes.STATIONS
  AND
    tblRoutes.ROUTES < tblRoutesCross.ROUTES
  AND
    (
       tblRoutesCross.STOPS = 0 
      OR
       tblRoutes.STOPS = 0 
    )

要查找非列车停止改变的路线或者在哪里找到路线:

  SELECT DISTINCT
    tblRoutes.ROUTES
   ,tblRoutesCross.ROUTES CrossingRoute
   --,tblRoutes.STATIONS
  FROM
    tblRoutes
  INNER JOIN
    tblRoutes tblRoutesCross
  ON
    tblRoutesCross.STATIONS = tblRoutes.STATIONS
  AND
    tblRoutes.ROUTES < tblRoutesCross.ROUTES
  AND
    (
       tblRoutesCross.STOPS = 0 
      AND
       tblRoutes.STOPS = 0 
    )

答案 1 :(得分:0)

我很抱歉我的代码,但我正在工作,我会稍后格式化,但这是你需要的步骤
希望它有所帮助

DECLARE @table TABLE (r NVARCHAR(3), s NVARCHAR(3), st BIT)
DECLARE @temp TABLE (r NVARCHAR(3), s NVARCHAR(100), st NVARCHAR(100))

INSERT INTO @table
        ( [r], [s], [st] )
VALUES  ('R1','S1',1 ),
        ('R1','S2',0),
        ('R1','S3',1),
        ('R1','S4',0),
        ('R1','S5',1),
        ('R2','S1',1),
        ('R2','S2',1),
        ('R2','S3',1),
        ('R2','S4',0),
        ('R2','S5',1),
        ('R3','S1',1),
        ('R3','S2',0),
        ('R3','S4',1),
        ('R3','S5',0),
        ('R3','S6',1),
        ('R3','S7',1),
        ('R4','S1',1),
        ('R4','S2',1),
        ('R4','S3',0),
        ('R4','S4',1),
        ('R5','S2',1),
        ('R5','S3',0),
        ('R5','S4',1)

SELECT * FROM @table

INSERT INTO @temp
        ( [r], [s], [st] )

SELECT DISTINCT r ,(
Select s + ',' AS 'data()' 
            From @table R2
            WHERE R2.[r] = [R].r
            ORDER BY [r]
            For XML PATH ('') ) [Routs]
            , (
Select CAST([st]AS NVARCHAR(2)) + ',' AS 'data()' 
            From @table R2
            WHERE R2.[r] = [R].r
            ORDER BY [r]
            For XML PATH ('') ) [Stops]
    FROM @table R

SELECT * FROM @temp

SELECT * FROM @temp WHERE [s] IN (SELECT [s] FROM @temp GROUP BY s HAVING COUNT(*) > 1 )

SELECT T.* FROM @temp T
INNER JOIN (
SELECT [s], [st] FROM @temp WHERE [r] IN (
 SELECT [r] FROM @temp WHERE [s] IN 
    ( SELECT [s] FROM @temp GROUP BY s HAVING COUNT(*) > 1 ) )
    GROUP BY [s], [st] HAVING COUNT (*) = 1 ) X ON T.[s] = X.[s] AND T.[st] = X.[st]

答案 2 :(得分:0)

我假设一个TrainRoutes表,每个R1,R2等都有一行。如果需要,可以用Stops中的select distinct RouteID替换它。

Select
    r1.RouteID Route1,
    r2.RouteID Route2
From
    -- cross to compare each route with each route
    dbo.TrainRoutes r1
        Cross Join
    dbo.TrainRoutes r2
        Inner Join
    dbo.Stops s1
        On r1.RouteID = s1.RouteID
        Inner Join
    dbo.Stops s2
        On r2.RouteID = s2.RouteID
Where
    r1.RouteID < r2.RouteID -- no point in comparing R1 with R2 and R2 with R1
Group By
    r1.RouteID,
    r2.RouteID
Having
     -- check each route has the same number of stations
    count(Distinct s1.stationID) = count(Distinct s2.stationID) And
    -- check each route has the same stops
    Sum(Case When s1.StationID = s2.StationID Then 1 Else 0 End) = count(Distinct s1.StationID) And
    -- check each route has different halts
    sum(Case When s1.StationID = s2.StationID And s1.Halts = s2.Halts Then 1 Else 0 End) != count(Distinct s1.StationID)

您也可以在没有TrainRoute表的情况下执行此操作,但现在您正在交叉连接两个较大的表:

Select
    s1.RouteID Route1,
    s2.RouteID Route2
From
    dbo.Stops s1
        Cross Join
    dbo.Stops s2
Where
    s1.RouteID < s2.RouteID
Group By
    s1.RouteID,
    s2.RouteID
Having
    count(Distinct s1.stationID) = count(Distinct s2.stationID) And
    Sum(Case When s1.StationID = s2.StationID Then 1 Else 0 End) = count(Distinct s1.StationID) And
    sum(Case When s1.StationID = s2.StationID And s1.Halts = s2.Halts Then 1 Else 0 End) != count(Distinct s1.StationID)

http://sqlfiddle.com/#!6/76978/8

答案 3 :(得分:0)

这里真正的挑战是找到经过相同站点的路线。我们的想法是通过在桌面上进行自我联接来比较两条路线,即compa和compb。当然,这种比较着眼于所有对。

现在,如果我们汇总一些有关路线的信息,我们可以确定它们是否具有相同的站点:

  • 按站加入,因此只计算匹配
  • 计算compA和compB上的电台数量
  • 计算两者的数字

第一个是连接的条件,第二个是使用窗口函数处理以在连接之前进行计数,第三个是连接的结果。

当所有这些计数相同时,两条路线通过同一站。

够容易。现在我们只需要添加一些站点在一条路线上停靠但不在另一条路线上的站点。

以下查询包含此逻辑:

select compa_Route, compb_Route
from (select compa.route as compa_route, compb.route as compb_Route,
             MAX(compa.numstations) as compa_NumStations,
             MAX(compb.NumStations) as compb_NumStations,
             SUM(case when compa.stop <> compb.stop then 1 else 0 end) as DifferentStops,
             COUNT(*) as both_NumStations
      from (select t.*, COUNT(*) over (partition by route) as numstations
            from t
           ) routea join
           (select t.*, COUNT(*) over (partition by route) as numstations
            from t
           ) routeb
           on routea.station = routeb.station and
              routea.route < routeb.route
      group by compa.route, compb.route
     ) ab
where compa_NumStations = compb_NumStations and
      compa_NumStations = both_NumStations and
      DifferentStops > 0

请注意,这假设站点不会在路线上重复。如果站点可以重复,那么问题就会变得有点困难。

答案 4 :(得分:0)

在SQLServer2005 +中使用递归CTE(公用表表达式)来查找所有站点并总结列车停靠点来比较它们

;WITH cte (id, r, s, st, max_level) AS
 (
  SELECT ROW_NUMBER() OVER(PARTITION BY t.r ORDER BY (SELECT 1)) as id,
         t.r, t.s, t.st,
         COUNT(*) OVER(PARTITION BY t.r) AS max_level
  FROM dbo.test11 t
  ), cte2 (id, r, s, st, max_level) AS
 (
  SELECT id, r, s, st, max_level
  FROM cte
  WHERE id = 1
  UNION ALL
  SELECT c.id, c.r, CAST(ISNULL(ct.s, '') + ', ' + ISNULL(c.s, '') AS nvarchar(100)) AS s,
         ct.st + c.st, c.max_level
  FROM cte c JOIN cte2 ct ON c.id = ct.id + 1 AND c.r = ct.r
)
SELECT c.r, c.s, c.st
FROM cte2 c JOIN cte2 ct ON c.s = ct.s AND c.r <> ct.r AND c.st <> ct.st
WHERE c.id = c.max_level AND ct.id = ct.max_level

SQLFiddle上的演示

答案 5 :(得分:-1)

只搜索没有余数的关系部门或确切的关系部门。