5

ここに私のテーブルがあります:

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

最初にすべてのルートをグループ化し、そのグループに属するステーションを他のすべてのステーションと比較して、少なくとも 1 つの異なるストップがあるかどうかを確認することを考えました。

4

6 に答える 6

1

次のクエリは、列車の1つが停止しないルートと駅を返します。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 
    )

どの列車も停車しないルートを見つけるには、またはwhere句で次のように変更します。

  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 
    )
于 2012-11-16T15:56:32.583 に答える
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のデモ

于 2012-11-17T18:28:57.993 に答える
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]
于 2012-11-16T16:17:12.113 に答える
0

R1、R2 などのそれぞれに 1 つの行を含む TrainRoutes テーブルを想定しました。必要に応じて、これをストップから個別の 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 テーブルを使用せずにこれを行うこともできますが、2 つの大きなテーブルをクロス結合しています。

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

于 2012-11-16T16:18:58.697 に答える
0

ここでの本当の課題は、同じ駅を通るルートを見つけることです。アイデアは、テーブルで自己結合を行うことによって、2 つのルート (compa と compb) を比較することです。もちろん、比較はすべてのペアを対象としています。

ここで、ルートに関する情報を集約すると、同じ駅があるかどうかを判断できます。

  • 駅ごとに参加するので、一致したものだけがカウントされます
  • compA と compB のステーション数を数えます。
  • 両方の数を数えます

1 つ目は結合の条件、2 つ目は結合前にウィンドウ関数を使用して処理され、3 つ目は結合の結果です。

これらのカウントがすべて同じ場合、2 つのルートは同じ駅を通過します。

簡単です。ここで、一方のルートには停車駅があるが、もう一方のルートには停車駅がない駅がある場所を追加する必要があります。

次のクエリには、このロジックが組み込まれています。

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

これは、駅がルート上で繰り返されないことを前提としていることに注意してください。ステーションを繰り返すことができる場合、問題は少し難しくなります。

于 2012-11-16T16:22:12.293 に答える
-1

剰余なしの関係分割または正確な関係分割を検索するだけです。

于 2012-11-18T03:09:53.480 に答える