合并“喜欢”行

时间:2018-07-01 06:14:58

标签: sql tsql

我有一张location_from,locations_to和航班计数的表格。我想将行距等于另一行的到达行组合在一起(例如LA TO NY与NY TO LA组合),然后对类似的行进行求和。

我认为最好举个例子来解释。

之前

locations_from      locations_to      # of Flights
--------------------------------------------------
San Francisco, CA   Los Angeles, CA     29558
Los Angeles, CA     San Francisco, CA   32389
New York, NY        Los Angeles, CA     30389
Los Angeles, CA     New York, NY        35484
Las Vegas, NV       Los Angeles, CA     28363
Los Angeles, CA     Las Vegas, NV       34455
Honolulu, HI        Kahului, HI         46563
Kahului, HI         Honolulu, HI        16879
San Francisco, CA   New York, NY        44654
New York, NY        San Francisco, CA   25882

之后

From/To             From/To           # of Flights
---------------------------------------------------
San Francisco, CA   Los Angeles, CA      61947
New York, NY        Los Angeles, CA      65873
Las Vegas, NV       Los Angeles, CA      62818
Honolulu, HI        Kahului, HI          63442
San Francisco, CA   New York, NY         70536

我已经尝试过交叉连接

where a.locations_from = b.locations_to

这行得通,但我最终得到了两倍的行数(即LA TO NY的一列,NY TO LA的一列)

3 个答案:

答案 0 :(得分:2)

只需使用CASE ... END对机场进行“分类”,然后按该“已分类”对进行分组。

SELECT CASE
         WHEN [locations_from] > [locations_to]
           THEN [locations_to]
         ELSE
           [locations_from]
       END [From/To],
       CASE
         WHEN [locations_from] > [locations_to]
           THEN [locations_from]
         ELSE
           [locations_to]
       END [From/To],
       sum([# of Flights]) [# of Flights]
       FROM elbat
       GROUP BY CASE
                  WHEN [locations_from] > [locations_to]
                    THEN [locations_to]
                  ELSE
                    [locations_from]
                END,
                CASE
                  WHEN [locations_from] > [locations_to]
                    THEN [locations_from]
                  ELSE
                    [locations_to]
                END;

SQL Fiddle

这也是在相反方向上使用FULL JOIN的替代解决方案。

SELECT coalesce(t1.[locations_from], t2.locations_from) [locations_from],
       coalesce(t1.[locations_to], t2.locations_from) [locations_to],
       coalesce(t1.[# of Flights], 0) + coalesce(t2.[# of Flights], 0) [# of Flights]
       FROM elbat t1
            FULL JOIN elbat t2
                      ON t2.[locations_from] = t1.[locations_to]
                         AND t2.[locations_to] = t1.[locations_from]
       WHERE (t1.[locations_from] IS NULL
              AND t1.[locations_to] IS NULL
               OR t1.[locations_from] < t1.[locations_to])
             AND (t2.[locations_from] IS NULL
                  AND t2.[locations_to] IS NULL
                   OR t2.[locations_from] > t2.[locations_to]);

SQL Fiddle

答案 1 :(得分:2)

使用工会

Declare @YourTable Table (SomeRowID int,[locations_from] varchar(50),[locations_to] varchar(50),[# of Flights] int)
Insert Into @YourTable Values 
 (1,'San Francisco, CA','Los Angeles, CA',29558)
,(2,'Los Angeles, CA','San Francisco, CA',32389)
,(3,'New York, NY','Los Angeles, CA',30389)
,(4,'Los Angeles, CA','New York, NY',35484)
,(5,'Las Vegas, NV','Los Angeles, CA',28363)
,(6,'Los Angeles, CA','Las Vegas, NV',34455)
,(7,'Honolulu, HI','Kahului, HI',46563)
,(8,'Kahului, HI','Honolulu, HI',16879)
,(9,'San Francisco, CA','New York, NY',44654)
,(10,'New York, NY','San Francisco, CA',25882);

select [locations_from], [locations_to], sum([# of Flights])
from 
(
select [locations_from], [locations_to], [# of Flights] 
from @YourTable 
where [locations_from] < [locations_to] 
union all
select [locations_to], [locations_from],  [# of Flights] 
from @YourTable 
where [locations_from] > [locations_to] 
) t
group by [locations_from], [locations_to]

答案 2 :(得分:1)

另一个使用CROSS APPLY和条件聚合的选项

此示例假定您具有某种RowID

示例

Declare @YourTable Table (SomeRowID int,[locations_from] varchar(50),[locations_to] varchar(50),[# of Flights] int)
Insert Into @YourTable Values 
 (1,'San Francisco, CA','Los Angeles, CA',29558)
,(2,'Los Angeles, CA','San Francisco, CA',32389)
,(3,'New York, NY','Los Angeles, CA',30389)
,(4,'Los Angeles, CA','New York, NY',35484)
,(5,'Las Vegas, NV','Los Angeles, CA',28363)
,(6,'Los Angeles, CA','Las Vegas, NV',34455)
,(7,'Honolulu, HI','Kahului, HI',46563)
,(8,'Kahului, HI','Honolulu, HI',16879)
,(9,'San Francisco, CA','New York, NY',44654)
,(10,'New York, NY','San Francisco, CA',25882)

;with cte as ( 
    Select A.SomeRowID
          ,Loc1    = min(Loc)
          ,Loc2    = max(Loc)
          ,Flights = sum(Val)
     From  @YourTable A
     Cross Apply ( values ([locations_from],[# of Flights])
                         ,([locations_to]  ,0)
                 ) B (Loc,Val)
     Group By A.SomeRowID
) 
Select Loc1
      ,Loc2
      ,Flights=sum(Flights)
 From  cte
 Group By Loc1,Loc2

返回

Loc1             Loc2               Flights
Honolulu, HI     Kahului, HI        63442
Las Vegas, NV    Los Angeles, CA    62818
Los Angeles, CA  New York, NY       65873
Los Angeles, CA  San Francisco, CA  61947
New York, NY     San Francisco, CA  70536