SQL WHERE 匹配任何列中的任何值

SQL WHERE matching any value in any column

我需要一个 table A,其中包含 4 列订单号:Order1、Order2、Order3、Order4(我知道,这很糟糕,但这是给定的)。

而且我必须在 table B 中找到记录,其中匹配项是 table A 中任何顺序列中的任何值都可以在 B 列中以任何顺序排列:

A.Order1 = B.Order1 OR
A.Order1 = B.Order2 OR
A.Order1 = B.Order3 OR
A.Order1 = B.Order4 OR
A.Order2 = B.Order1 etc

有没有更好的写法? 我害怕他们告诉我他们想要使用 5 或 6 列的那一刻。

对原始问题的编辑

使用您拥有的模型设计来做到这一点的唯一方法是(正如@GordonLinoff 建议的那样):

where b.order1 in (a.order1, a.order2, a.order3, a.order4) or
      b.order2 in (a.order1, a.order2, a.order3, a.order4) or
      b.order3 in (a.order1, a.order2, a.order3, a.order4) or
      b.order4 in (a.order1, a.order2, a.order3, a.order4) 

您可能有一个有趣的问题,即如何更改我的数据模型以使其更好地工作? ... 方法如下:

首先你有两个 tableA 和 B。我假设 A 和 B 都有一个唯一的索引 ID。

然后您可以用以下列

支持table AOrder
AID 
ORDNUM
VALUE

如果您为 BOrder 创建了一个类似的 table,那么要查明给定的订单是否相同,只需加入 Value 即可获得 AID、BID 和两个订单号。

采用这种设计,您无需关心有多少订单号。

您可以像这样即时将当前数据转换为该设计并获得您想要的结果:

 SELECT aord.ID as aID, bord.ID as bID, a.num as a_ordernum, b.num as b.ordernum, v 
 FROM (
   SELECT a.ID, 1 AS num, a.order1 as V FROM a
     UNION ALL
   SELECT a.ID, 2 AS num, a.order2 as V FROM a
     UNION ALL
   SELECT a.ID, 3 AS num, a.order3 as V FROM a
     UNION ALL
   SELECT a.ID, 4 AS num, a.order4 as V FROM a
 ) aord
 JOIN (
   SELECT b.ID, 1 AS num, b.order1 as V FROM b
     UNION ALL
   SELECT b.ID, 2 AS num, b.order2 as V FROM b
     UNION ALL
   SELECT b.ID, 3 AS num, b.order3 as V FROM b
     UNION ALL
   SELECT b.ID, 4 AS num, b.order4 as V FROM b
 ) bord on aord.v = bord.v

你能把它们归一化吗?我假设您有一个 SetID 字段将 A 和 B 中的 4 个(或更多)订单分组,因此您可以有一个 table/view,例如:

    select ID, srctbl, seq, order
    from (
    select AID as ID, 'A' as srctbl, 1 as seq, order1 as order from tblA union all
    select AID, 'A' as srctbl, 2, order2 from tblA union all
    select AID, 'A' as srctbl, 3, order3 from tblA union all
    select AID, 'A' as srctbl, 4, order4 from tblA union all
    select BID, 'B' as srctbl, 1, order1 from tblB union all
    select BID, 'B' as srctbl, 2, order2 from tblB union all
    select BID, 'B' as srctbl, 3, order3 from tblB union all
    select BID, 'B' as srctbl, 4, order4 from tblB )

那你可以说

select ID, srctbl, seq, order 
from (select ID, srctbl, seq, order from tbl where srctbl = 'a') ta inner join
((select ID, srctbl, seq, order from tbl where srctbl = 'b') tb on
ta.order = tb.order

或者,作为 CTE:

WITH orders (ID, srctbl, SEQ, orderVal)
AS (
   SELECT ID, srctbl, SEQ, orderVal
    FROM (
    SELECT AID AS ID, 'A' AS srctbl, 1 AS SEQ, order1 AS orderVal FROM tblA UNION ALL
    SELECT AID, 'A' AS srctbl, 2, order2 FROM tblA UNION ALL
    SELECT AID, 'A' AS srctbl, 3, order3 FROM tblA UNION ALL
    SELECT AID, 'A' AS srctbl, 4, order4 FROM tblA UNION ALL
    SELECT BID, 'B' AS srctbl, 1, order1 FROM tblB UNION ALL
    SELECT BID, 'B' AS srctbl, 2, order2 FROM tblB UNION ALL
    SELECT BID, 'B' AS srctbl, 3, order3 FROM tblB UNION ALL
    SELECT BID, 'B' AS srctbl, 4, order4 FROM tblB )
)

SELECT ta.ID AS a_id, tb.ID AS b_ID, ta.SEQ AS a_seq, tb.SEQ AS b_seq, ta.orderVal 
FROM 
 (SELECT ID, SEQ, orderVal FROM orders WHERE srctbl = 'a') ta INNER JOIN
 (SELECT ID, SEQ, orderVal FROM orders WHERE srctbl = 'b') tb ON
ta.orderVal = tb.orderVal

您可以使用交叉应用取消透视一个 table 中的列,然后检查交叉应用的值是否在另一个 table 的任何列中。

如果您添加新列,它不会自动工作,但您只需在一两个地方添加它们。

SQL Fiddle

MS SQL Server 2014 架构设置:

create table A
(
  Order1 int,
  Order2 int,
  Order3 int,
  Order4 int
)

create table B
(
  Order1 int,
  Order2 int,
  Order3 int,
  Order4 int
)

insert into A values
(1, 1, 40, 10),
(2, 2, 2, 20)

insert into B values
(3, 3, 3, 30),
(4, 4, 4, 40)

查询 1:

select *
from A
where exists (
             select *
             from B
               cross apply (values(B.Order1),(B.Order2),(B.Order3),(B.Order4)) as X(O)
             where X.O in (A.Order1, A.Order2, A.Order3, A.Order4)
             )       

Results:

| Order1 | Order2 | Order3 | Order4 |
|--------|--------|--------|--------|
|      1 |      1 |     40 |     10 |