SQL:确定即使一个1:很多是另一个1:多

时间:2014-01-16 01:36:30

标签: mysql sql

考虑航运业,那里有移动物品的公司(运营商)和运送物品的公司(托运人)。每个都有基于州的路线。例如,托运人将东西从缅因州送到加利福尼亚州,从缅因州送到堪萨斯州,从新罕布什尔州送到阿拉巴马州等。同样,承运人也有“路线”,他们再次采取国家对州的定义。我想使用SQL查询快速为托运人选择承运人,该托运人在任何出货地/目的地与任何承运人路线之间至少有一个匹配。

数据库布局如下:

托运人与合同的关系为1:m。合同与车道的关系为1:m。通道以其最简单的术语originState和destinationState定义。

从这里开始,我需要查询所有可能的运营商,看看哪些运营商可以对该合同进行投标,这相当于运营商至少有一条支持的路线与任何一个合同通道相匹配。将运营商表与其所有“路由”进行1:m的关系,再次定义为originState和destinationState。

此时,我只需要匹配的运营商列表。我甚至不关心哪条路线匹配,只是他们有资格竞标合同。

谢谢!

根据要求,以下是当前查询:

SELECT DISTINCT
    r.id as contractId, c.id as carrierId
FROM
    contract r
        JOIN
    contractLane rl ON rl.contractId = r.id
        JOIN
    lane l on l.origState = rl.originState and l.destState = rl.destState /*carrier lane matches any contract lane*/
        JOIN 
    carrier c on c.id = l.companyId
        JOIN 
    user u ON u.id = l.masterId and u.type = 4 /* lane owner is a carrier */
WHERE
    r.expireDate >= NOW()
        AND r.open = '1'
        AND r.active = '1'

2 个答案:

答案 0 :(得分:0)

SELECT S.id, S.originState, S.destinationState
FROM carrier AS C, shipper AS S
WHERE (C.originState = S.originState
    OR C.originState = S.destinationState
    OR C.destinationState = S.originState
    OR C.destinationState = S.destinationState)
    AND C.id = 34

34是您要过滤的运营商的ID。

你也可以用JOIN做同样的事情。

答案 1 :(得分:0)

根据您的描述,它非常简单。这假设每个表的主键为id,外键列的格式为table_id

以下是获得结果的一种方法:

 SELECT c.*
   FROM carrier c
   JOIN route r
     ON r.carrier_id = c.id
   JOIN lane l
     ON l.originState = r.originState
    AND l.destinationState = r.destinationState
   JOIN contract o
     ON o.id = l.contract_id
   JOIN shipper s
     ON s.id = o.shipper_id
  GROUP BY c.id
  • 每个承运人都有零个,一个或多个路线。
  • 每条路线都有起始和目的地状态。
  • 每个托运人合同“lane”都有起始和目的地状态。
  • 如果原始和目的地状态匹配,路线将匹配“车道”。
  • “lane”引用单一合约。
  • 合同引用单个托运人。

可能存在多个匹配,因此我们使用运营商表的GROUP BY pk返回唯一的运营商列表。