SQL连接和条件求和

时间:2017-12-15 02:21:15

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

我有两个表,设置如下:

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表中选择与Zone表中的ZE列匹配的行条目。例如:

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),其中总行程将在特定区域编号上进行求和(Origin或{{1}取决于哪个列匹配区域等效Destination数字)。

例如,对于Zone 1,Origin 1101,我希望该行条目的新Destination值为Distribution

我尝试过以下代码

0.6/(0.6+0.7+0.8)

我不确定这是否会产生正确的结果,因为没有group by子句我得到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.

Divide by zero error encountered.开始,不应该有任何inner join为零,所以我不确定为什么会收到此错误。

请帮忙!

编辑:我现在使用查询

获取重复行
sums

更新了表格以显示错误:

ZE:

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

PMX:

Precinct    Zone    
1           1101    
2           1102    
3           1111    
4           1211

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

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    

编辑2:我想创建一个'if语句',以便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 然后Pmx.origin =ZE.Zone如上所述trips_div。但是,如果trips/SUM(Trips) over(partition by Pmx.Origin)Pmx.origin =ZE.Zone,我希望Pmx.destination=ZE.Zone仍为trips_div。当trips/SUM(Trips) over(partition by Pmx.Origin)Pmx.origin does not equal ZE.Zone然后Pmx.destination=ZE.Zone时。我尝试了各种trips/SUM(Trips) over(partition by Pmx.Destination)语句,但似乎无法使其发挥作用。

我希望输出为:

case when

1 个答案:

答案 0 :(得分: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 |