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 列的那一刻。
对原始问题的编辑
- 这适用于 SQL Server 2008 R2
- Table B也有4个订单栏,订单号
- 我正在寻找 Table A 中任何订单列中的任何订单号,以匹配 Table B 中任何订单列中的任何订单号。
- 没有预期的最有可能的发现
使用您拥有的模型设计来做到这一点的唯一方法是(正如@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 的任何列中。
如果您添加新列,它不会自动工作,但您只需在一两个地方添加它们。
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)
)
| Order1 | Order2 | Order3 | Order4 |
|--------|--------|--------|--------|
| 1 | 1 | 40 | 10 |
我需要一个 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 列的那一刻。
对原始问题的编辑
- 这适用于 SQL Server 2008 R2
- Table B也有4个订单栏,订单号
- 我正在寻找 Table A 中任何订单列中的任何订单号,以匹配 Table B 中任何订单列中的任何订单号。
- 没有预期的最有可能的发现
使用您拥有的模型设计来做到这一点的唯一方法是(正如@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 AOrderAID
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 的任何列中。
如果您添加新列,它不会自动工作,但您只需在一两个地方添加它们。
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)
)
| Order1 | Order2 | Order3 | Order4 |
|--------|--------|--------|--------|
| 1 | 1 | 40 | 10 |