sql查询过滤器在另一个表中使用的行

时间:2019-03-18 17:01:39

标签: sql tsql

我有三个表...

表1 消息类型

表2 businesschannel ,其列为:idBusinessChannel,idsystem,idMessageType,方向

表3 合作伙伴系统消息,其中包括: idSystem, idMessageType

我需要编写一个查询,该查询返回消息类型列表,该列表散发partnersystemmessages(idSystem列)表和businesschannel(方向列)已使用的消息。

到目前为止,我有以下查询,该查询返回消息类型列表,但忽略方向

SELECT    DISTINCT messagetype.*
FROM      messagetype
LEFT OUTER JOIN BUSINESSCHANNEL bc ON 
    bc.idMessageType = messagetype.idMessageType 
    AND bc.direction = 'out'
LEFT JOIN partnersystemmessages ON  
    messagetype.idMessageType = partnersystemmessages.idMessageType
      AND partnersystemmessages.idSystem = 522
WHERE     partnersystemmessages.idMessageType IS NULL 

更新-添加示例数据

messagetype
+--------------+----------+
| idMessageType| Name     | 
+--------------+----------+
| 1            | SMTP     | 
| 2            | EDI      | 
| 3            | AS2      | 
| 4            | WED      | 
| 5            | IDOC     | 
| 6            | general  | 
+--------------+----------+



businesschannel 
+------------------------+----------+---------------+------------+
| idpartnersystemmessages| idsystem | idMessageType | direction| |
+------------------------+----------+---------------+------------+
| 1859                   | 522      |     2         |  in        |
| 5131                   | 522      |     1         |  out       |
| 1773                   | 522      |     2         |  out       |
| 1775                   | 522      |     3         |  in        |
| 1777                   | 522      |     4         |  out       |
| 4555                   | 522      |     5         |  in        |
+------------------------+----------+---------------+------------+
partnersystemmessages 
+-------------------------+----------------+---------------+
| idpartnersystemmessages |MessageidSystem | |idMessageType|
+-------------------------+----------------+---------------+
| 1859                    |   522          |     2        |
| 5131                    |   522          |     1        |  
| 1773                    |   522          |     2        | 
| 1775                    |   522          |     3        |  
| 1777                    |   522          |     4        |  
| 4555                    |   522          |     5        |  
--------------------------+----------------+--------------+

对于idSystem = 522和direction ='out' 我期望:

 messagetype
+--------------+----------+
| idMessageType| Name     | 
+--------------+----------+
| 1            | SMTP     | 
| 3            | AS2      | 
| 5            | idoc     | 
| 6            | general  | 
+--------------+----------+

不包括已经用于外向的EDI和WEB

2 个答案:

答案 0 :(得分:0)

尝试通过更改连接如下所示

SELECT    DISTINCT m.*
FROM      messagetype m
LEFT OUTER JOIN BUSINESSCHANNEL bc ON 
    bc.idMessageType = m.idMessageType 
       JOIN partnersystemmessages ON  
     bc.idsystem= partnersystemmessages.idsystem
      AND partnersystemmessages.idSystem = 522

WHERE     bc.idMessageType IS NULL 

答案 1 :(得分:0)

由于要将两个表重新连接到需要排除的主表,因此请将两个条件都添加到WHERE中。 LEFT JOIN.... IS NULL模式通常表现出色,尽管NOT EXISTS()通常也可以很好地工作,并且可能是更好的选择。您必须对数据进行测试。

完整查询

SELECT *
FROM messagetype mt
LEFT OUTER JOIN businesschannel bc ON bc.idMessageType = mt.idMessageType 
    AND bc.direction = 'out'
LEFT OUTER JOIN partnersystemmessages psm ON mt.idMessageType = psm.idMessageType
    AND psm.idSystem = 522

Results

| idMessageType |    Name | idBusinessChannel | idsystem | idMessageType | direction | idSystem | idMessageType |
|---------------|---------|-------------------|----------|---------------|-----------|----------|---------------|
|             1 |    SMTP |                 2 |      522 |             1 |       out |      522 |             1 |
|             2 |     EDI |                 3 |      522 |             2 |       out |      522 |             2 |
|             2 |     EDI |                 3 |      522 |             2 |       out |      522 |             2 |
|             3 |     AS2 |            (null) |   (null) |        (null) |    (null) |      522 |             3 |
|             4 |     WED |                 5 |      522 |             4 |       out |      522 |             4 |
|             5 |    IDOC |            (null) |   (null) |        (null) |    (null) |      522 |             5 |
|             6 | general |            (null) |   (null) |        (null) |    (null) |   (null) |        (null) |

首先,您的原始问题似乎表明您想从messagetype中排除与businesschannelpartnersystemmessages匹配的行。但是,您的示例结果显示的行仅限于同时显示。

使用左连接...为空

SELECT DISTINCT mt.*
FROM messagetype mt
LEFT OUTER JOIN businesschannel bc ON bc.idMessageType = mt.idMessageType 
    AND bc.direction = 'out'
LEFT OUTER JOIN partnersystemmessages psm ON mt.idMessageType = psm.idMessageType
    AND psm.idSystem = 522
WHERE bc.idBusinessChannel IS NULL
    OR psm.idSystem IS NULL

Results

| idMessageType |    Name |
|---------------|---------|
|             3 |     AS2 |
|             5 |    IDOC |
|             6 | general |

使用“不存在”

SELECT DISTINCT mt.*
FROM messagetype mt
WHERE NOT EXISTS (
    SELECT 1 FROM businesschannel bc 
    WHERE bc.direction = 'out'
        AND bc.idMessageType = mt.idMessageType 
  ) 
  OR NOT EXISTS (
      SELECT 1 FROM partnersystemmessages psm 
      WHERE psm.idSystem = 522
          AND psm.idMessageType = mt.idMessageType
  )

Results

| idMessageType |    Name |
|---------------|---------|
|             3 |     AS2 |
|             5 |    IDOC |
|             6 | general |

OR更改为AND会将结果进一步限制为仅general。我仍不清楚您的原始结果为何包含SMTP。我原来的查询显示它包含在两个表中。那是错字吗?