Self Join 或 EXISTS 在这里有帮助吗?

Does a Self Join or EXISTS Help here?

我正在使用 Advantage Server 12。 我需要一个结果集,当提供的参数出现在主数据或详细信息中时 table 当提供的值不是链接字段时查找所有记录。

客户Table

  |AccountCode |Tel1|Tel2|Tel3|Accout Name/Address etc....
  |   ACODE    |    |    |    |

N < 2

联系Table

  |AccountCode |cTel1|cTel2|cTel3|ContactName/Address etc....
  |   ACODE    |     |     |     |

N >=0

需要来自客户的行和来自联系人的 所有 具有匹配 ACODE 的行。 当提供 Tel1 或 Tel2 或 Tel3 cTel1 或 cTel2 或 cTel3 时

当在任何客户字段中找到提供的值 ('thenumber') 时,此 SQL 给出所需的结果 当在联系人 table 中找到提供的号码时,它 returns 客户字段和联系人

中匹配行的唯一数据
declare @Tel string;

set @Tel = 'thenumber';
      
 select
  @TEL as calling,c.Tel1,c.Tel2,c.contact as "Primary",
  c.acnt_nmbr,c.Acnt_name, a.contact,a.cTel1 as telephone1,a.cTel2 as telephone2
 from
  customer c 
 full outer join contact a on (c.acnt_nmbr=a.acnt_nmbr)
 where
  replace(c.Tel1,' ','') = @Tel
   or
  replace(c.Tel2,' ','') = @Tel 
   or
  replace(c.Tel3,' ','') = @Tel
   or 
  replace(a.cTel1,' ','') = @Tel
   or
  replace(a.cTel2,' ','') = @Tel 
   or
  replace(a.cTel3,' ','') = @Tel

在客户中找到 'thenumber' 时的结果 - 这就是我们想要的

calling   Tel1     Tel2      Primary  acnt_nmbr Acnt_name contact telephone1 telephone2 
thenumber 11111111 thenumber KIERAN   687       theCo     Pat     12234560   333444555  
thenumber 11111111 thenumber KIERAN   687       theco     Mary    45678900   444555666  
thenumber 11111111 thenumber KIERAN   687       theco     Jon     22233344  
thenumber 11111111 thenumber KIERAN   687       theco     Paul    22244455   124578111  
thenumber 11111111 thenumber KIERAN   687       theco     Jane    33225544  

在联系人中找到 'thenumber' 时的结果 - 我们需要与上面相同的结果集

calling   Tel1      Tel2      Primary  acnt_nmbr Acnt_name  contact  telephone1 telephone2  
thenumber 11111111  2222222   KIERAN   687       theco      Jane     thenumber  

我在想一些自连接或 EXISTS 语句是答案,但不确定如何继续。

这比您预期的要棘手一些,就我刚刚看到您的最新评论而言,我希望我向您提出的解决方案能够奏效(我根本不了解 SAP 技术环境)。

就你的SQL点,我的处理方法如下。
对于客户和联系人,找到匹配的值。这对客户来说很容易,但对于联系人,您需要识别单个匹配值,然后在所有值都匹配的地方保留联系人
然后,构建客户和联系人的集合。
最后,合并来自两个第一个过滤器的结果,与基础数据相结合。

这是我提出的最终要求:

with cust_check as (
    SELECT account_code, tel1, tel2, tel3, address,
           CASE WHEN tel1 = @Tel THEN 1
                ELSE CASE WHEN tel2 = @Tel THEN 1
                          ELSE CASE WHEN tel3 = @Tel THEN 1
                                    ELSE 0
                               END
                     END
           END as cust_match
    from customer
),
cust_filter as (
    SELECT account_code, tel1, tel2, tel3, address AS detail 
     FROM cust_check
    WHERE cust_match = 1
),
contact_check as (
    SELECT account_code, ctel1, ctel2, ctel3, cname,
           CASE WHEN ctel1 = @Tel THEN 1
                ELSE CASE WHEN ctel2 = @Tel THEN 1
                          ELSE CASE WHEN ctel3 = @Tel THEN 1
                                    ELSE 0
                               END
                     END
           END as contact_match
    FROM contact
),
contact_filter as (
    SELECT account_code, count(*) as nb_rows, sum(contact_match) as nb_matched
     FROM contact_check
    GROUP BY account_code
    HAVING count(*) = sum(contact_match)
),
all_contacts as (
    SELECT t.account_code, ctel1, ctel2, ctel3, cname, address
      FROM contact as t
      JOIN customer as c ON c.account_code = t.account_code
),
union_match as 
(
    SELECT c.account_code, c.ctel1, c.ctel2, c.ctel3, c.cname, c.address
      FROM all_contacts c
      JOIN cust_filter f ON f.account_code = c.account_code
    UNION
    SELECT c.account_code, c.ctel1, c.ctel2, c.ctel3, c.cname, c.address
      FROM all_contacts c
      JOIN contact_filter f ON f.account_code = c.account_code
)
SELECT account_code, ctel1, ctel2, ctel3, cname, address
  FROM union_match

此请求基于 MS SQL 服务器,由于 DB-Fiddle,您可以轻松地 'play' 使用它 - 我只希望它符合您的限制!

这应该可以达到你想要的效果:

 select
  @TEL as calling,c.Tel1,c.Tel2,c.contact as "Primary",
  c.acnt_nmbr,c.Acnt_name, a.contact,a.cTel1 as telephone1,a.cTel2 as telephone2
 from
  customer c 
 left join contact a on (c.acnt_nmbr=a.acnt_nmbr)
 WHERE c.acnt_nmbr IN
 (
 SELECT DISTINCT acnt_nmbr FROM 
  (SELECT acnt_nmbr, Tel1, Tel2
   FROM Customer
   UNION
   SELECT acnt_nmbr, cTel1, cTel2
   FROM Contact) x
  WHERE
   replace(x.Tel1,' ','') = @Tel
   or
  replace(x.Tel2,' ','') = @Tel
 ) 

(我会留给你解决如何添加 Tel3 :)

请注意,我已将您的完整外部联接更改为简单的左联接,因为所提供的代码不适用于无客户联系人。

如果你真的需要全外连接,代码会变得有点复杂:

SELECT z.* FROM
( select @TEL as calling,c.Tel1,c.Tel2,c.contact as "Primary",
  COALESCE(c.acnt_nmbr,a.acnt_nmbr) AS AccountNo, 
  c.Acnt_name, a.contact,a.cTel1 as telephone1,a.cTel2 as telephone2
 from
  Customer c 
 full outer join Contact a on (c.acnt_nmbr=a.acnt_nmbr)
) z
WHERE COALESCE(z.AccountNo,0) IN
(...)

我已修改 Christophe's DB-fiddle 以显示此功能。

请注意,完全外部联接的解决方案在 fiddle 中略有不同,以应对 Microsoft SQL 服务器与 Advantage 数据库服务器相比的不同行为。 (例如,对于 ADS DBF 表,整数字段中的 NULL 值在 UNION 中变为零)。