【问题标题】:SQL Joins and Conditional SumsSQL 连接和条件求和
【发布时间】:2017-12-15 02:21:15
【问题描述】:

我有两张表,设置如下:

PMmx - 起点-终点矩阵的表格版本

Origin  Destination Trips
1           1        0.2
2           1        0.3
3           1        0.4
.           .         .
.           .         .
1         1101       0.6
2         1101       0.7
3         1101       0.8
.          .          .
.          .          .     
1101       1         0.2
1101       2         0.3
1101       3         0.4

ZE - 具有区域等效性的表

Precinct    Zone
1           1101
2           1102
3           1111

我想在PMmx 表中选择与ZE 表中的Zone 列匹配的行条目。例如:

Origin  Destination Trips
1         1101       0.6
2         1101       0.7
3         1101       0.8
.          .          .
.          .          .     
1101       1         0.2
1101       2         0.3
1101       3         0.4

我还想创建一个名为Distribution 的新列,它计算Trips/(Total Trips),其中总行程将在特定区域编号上求和(通过OriginDestination 取决于哪一列与区域匹配等价 Zone 数字)。

例如,对于Origin 1、Destination 1101,我希望该行条目的新Distribution 值为0.6/(0.6+0.7+0.8)

我试过下面的代码

SELECT 
      PMmx.Origin                  as Origin
     ,PMmx.Destination             as Destination
     ,PMmx.Trips/sum(PMmx.Trips) as 'Distribution'
FROM PMmx

inner join ZE on Origin=ZE.Zone or Destination=ZE.Zone 

Group by Origin, Destination, Trips

我不确定这是否会产生正确的结果,因为没有 group by 子句我得到 Column '2DVISUM_2031PMmx_unpiv.Origin' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. 而使用 group by 子句我得到 Divide by zero error encountered.

inner join 开始,不应该有任何 sums 为零,所以我不确定为什么会收到此错误。

请帮忙!

编辑:我现在使用查询得到重复的行

with cte as (
  select
     origin, destination, trips
  , SUM(Trips) over(partition by Pmx.Origin) sum_trips
  , trips / SUM(Trips) over(partition by Pmx.Origin) trips_div
  from Pmx
  inner join ZE on Pmx.Origin = ZE.Zone
  )
select
origin, destination, trips, sum_trips, trips_div
from cte
union all
select
destination, origin, trips, sum_trips, trips_div
from cte

更新表格以显示错误:

ZE:

Precinct    Zone    
1           1101    
2           1102    
3           1111    
4           1211

Pmx:

Origin  Destination Trips
1           1       0.20
2           1       0.30
3           1       0.40
1          1101     0.60
2          1101     0.70
3          1101     0.80
1101        1       0.20
1101        2       0.30
1101        3       0.40
1101       1211     0.60
1211       1101     0.50    

输出包含具有不同行程值的重复项:

origin destination trips sum_trips trips_div

1101    1   0.20    1.50    0.13333333333333333333333333
1101    2   0.30    1.50    0.20000000000000000000000000
1101    3   0.40    1.50    0.26666666666666666666666666
1101  1211  0.60    1.50    0.40000000000000000000000000
1211  1101  0.50    0.50    1.00000000000000000000000000
1     1101  0.20    1.50    0.13333333333333333333333333
2     1101  0.30    1.50    0.20000000000000000000000000
3     1101  0.40    1.50    0.26666666666666666666666666
1211  1101  0.60    1.50    0.40000000000000000000000000
1101  1211  0.50    0.50    1.00000000000000000000000000

编辑 2: 我想创建一个“if 语句”,这样如果 Pmx.origin =ZE.Zonetrips_divtrips/SUM(Trips) over(partition by Pmx.Origin) 如上所述。但是,如果 Pmx.origin =ZE.ZonePmx.destination=ZE.Zone 那么我希望 trips_div 仍然是 trips/SUM(Trips) over(partition by Pmx.Origin)。当Pmx.origin does not equal ZE.ZonePmx.destination=ZE.Zone 然后trips/SUM(Trips) over(partition by Pmx.Destination)。我尝试了各种case when 语句,但似乎无法正常工作。

我希望输出是:

origin destination trips sum_trips trips_div

    1     1101  0.20    2.10    0.0952380952380952
    2     1101  0.30    2.10    0.1428571428571429
    3     1101  0.40    2.10    0.1904761904761905
    1101    1   0.20    1.50    0.1333333333333333
    1101    2   0.30    1.50    0.2000000000000000
    1101    3   0.40    1.50    0.2666666666666666
    1101  1211  0.60    1.50    0.4000000000000000
    1211  1101  0.50    0.50    1.0000000000000000

【问题讨论】:

  • 响应您的“编辑 2”请参阅 sqlfiddle.com/#!6/e8020/6 那个 case 表达式是 case when Pmx.origin <> ZE.Zone and Pmx.destination = ZE.Zone then trips/SUM(Trips) over(partition by Pmx.Destination) else trips/SUM(Trips) over(partition by Pmx.Origin) end 但它对结果没有影响。

标签: sql sql-server group-by sum inner-join


【解决方案1】:

如果我了解您的要求,我认为您可以对总和使用稍微不同的方法,从而使该总和可用于源表的每一行。有了这个,你就不需要 group by 子句了。

SELECT 
       PMmx.Origin                  as Origin
     , PMmx.Destination             as Destination
     , (PMmx.Trips/sum(PMmx.Trips) over(partition by Destination)) as 'Distribution'
FROM PMmx
inner join ZE on Origin=ZE.Zone or Destination=ZE.Zone 

SQL Fiddle

MS SQL Server 2014 架构设置

CREATE TABLE Pmx
    ([Origin] int, [Destination] int, [Trips] decimal(12,2))
;
    
INSERT INTO Pmx
    ([Origin], [Destination], [Trips])
VALUES
    (1, 1, 0.2),
    (2, 1, 0.3),
    (3, 1, 0.4),
    (1, 1101, 0.6),
    (2, 1101, 0.7),
    (3, 1101, 0.8),
    (1101, 1, 0.2),
    (1101, 2, 0.3),
    (1101, 3, 0.4)
;


CREATE TABLE ZE
    ([Precinct] int, [Zone] int)
;
    
INSERT INTO ZE
    ([Precinct], [Zone])
VALUES
    (1, 1101),
    (2, 1102),
    (3, 1111)
;

查询 1

with cte as (
  select
     origin, destination, trips
  , SUM(Trips) over(partition by Pmx.Origin) sum_trips
  , trips / SUM(Trips) over(partition by Pmx.Origin) trips_div
  from Pmx
  inner join ZE on Pmx.Origin = ZE.Zone
  )
select
origin, destination, trips, sum_trips, trips_div
from cte
union -- changed to union so duplication is avoided
select
destination, origin, trips, sum_trips, trips_div
from cte

Results

| origin | destination | trips | sum_trips |          trips_div |
|--------|-------------|-------|-----------|--------------------|
|   1101 |           1 |   0.2 |       0.9 | 0.2222222222222222 |
|   1101 |           2 |   0.3 |       0.9 | 0.3333333333333333 |
|   1101 |           3 |   0.4 |       0.9 | 0.4444444444444444 |
|      1 |        1101 |   0.2 |       0.9 | 0.2222222222222222 |
|      2 |        1101 |   0.3 |       0.9 | 0.3333333333333333 |
|      3 |        1101 |   0.4 |       0.9 | 0.4444444444444444 |

第 2 部分

SQL Fiddle

MS SQL Server 2014 架构设置

CREATE TABLE Pmx
    ([Origin] int, [Destination] int, [Trips] decimal(12,2))
;
    
INSERT INTO Pmx
    ([Origin], [Destination], [Trips])
VALUES
    (1, 1, 0.20),
    (2, 1, 0.30),
    (3, 1, 0.40),
    (1, 1101, 0.60),
    (2, 1101, 0.70),
    (3, 1101, 0.80),
    (1101, 1, 0.20),
    (1101, 2, 0.30),
    (1101, 3, 0.40),
    (1101, 1211, 0.60),
    (1211, 1101, 0.50)
;


CREATE TABLE ZE
    ([Precinct] int, [Zone] int)
;
    
INSERT INTO ZE
    ([Precinct], [Zone])
VALUES
    (1, 1101),
    (2, 1102),
    (3, 1111),
    (4, 1211)
;

查询 1

with cte as (
  select
     origin, destination, trips
  , SUM(Trips) over(partition by Pmx.Origin) sum_trips
  , trips / SUM(Trips) over(partition by Pmx.Origin) trips_div
  from Pmx
  inner join ZE on Pmx.Origin = ZE.Zone
  )
select
origin, destination, trips, sum_trips, trips_div
from cte
union
select
destination, origin, trips, sum_trips, trips_div
from cte
order by 1,2,3,4

Results

| origin | destination | trips | sum_trips |           trips_div |
|--------|-------------|-------|-----------|---------------------|
|      1 |        1101 |   0.2 |       1.5 | 0.13333333333333333 |
|      2 |        1101 |   0.3 |       1.5 |                 0.2 |
|      3 |        1101 |   0.4 |       1.5 | 0.26666666666666666 |
|   1101 |           1 |   0.2 |       1.5 | 0.13333333333333333 |
|   1101 |           2 |   0.3 |       1.5 |                 0.2 |
|   1101 |           3 |   0.4 |       1.5 | 0.26666666666666666 |
|   1101 |        1211 |   0.5 |       0.5 |                   1 |
|   1101 |        1211 |   0.6 |       1.5 |                 0.4 |
|   1211 |        1101 |   0.5 |       0.5 |                   1 |
|   1211 |        1101 |   0.6 |       1.5 |                 0.4 |

【讨论】:

  • 非常感谢!当我被困在如何正确地做它时,我最终将我的问题分成多个表,并且以某种方式结束了重复的行(必须来自不正确的连接)。一旦阅读了您的帖子,我就以这种方式重新完成了它,这一切似乎都奏效了!谢谢!
  • 我说得太早了@Used_By_Already!对于起点和终点都与等价表 ZE 匹配的条目,我现在似乎得到了重复的行。例如,在 Pmx 中,Origin 为 1101,destination 为 1102。我似乎不明白为什么会这样?
  • 我不知道您能否添加允许复制问题的示例数据。
  • 似乎使用上面的查询 1,我得到了两行用于起点 1101 目的地 1102 的行程,因为行程看起来不同,因为它从起点 1102 目的地 1101 条目开始行程并将其列为起点 1101目的地 1102。好的,我现在再添加一些数据。
  • 我已经更新了我的问题,最后进行了编辑 - 谢谢@Used_By_Already!
猜你喜欢
  • 1970-01-01
  • 2016-03-15
  • 1970-01-01
  • 1970-01-01
  • 2014-04-14
  • 1970-01-01
  • 1970-01-01
  • 2015-08-28
  • 1970-01-01
相关资源
最近更新 更多