基于多个条件的 SQL 查询

Posted

技术标签:

【中文标题】基于多个条件的 SQL 查询【英文标题】:SQL query based on multiple criteria 【发布时间】:2014-08-04 14:27:38 【问题描述】:

基本上我有 2 张桌子。 1 个表有两个(重要)列的列表。一般的想法是,第 2 列中的项目不能与第 1 列中的项目组合出售。它本质上是一组确定正确计费组合的规则。该表与此类似:

col 1   ;  col 2
-----     -----
  a     ----    b
  a     ----    h
  a     ----    d
  b     ----    f
  b     ----    z
  c     ----    z
  c     ----    d
  c     ----    b

第 1 列中的商品不能与第 2 列中的商品一起出售。

第二个表本质上是一个“订单”表。每笔交易都有交易编号和行号。在每个交易行上都有已售出的项目。每笔交易通常会出售 许多 件商品。该表的设置与此类似:

trans # ;    trans line  ;   item
-------     -----------    -----
12345    ----       1    ----        a
12345      ----     2      ----      b
12345       ----    3    ----        a
45678      ----     1   ----         z
45678       ----    2      ----      f

我要做的是获取所有交易数据,并将其与不适当项目组合列表中的数据进行核对。如您所见,交易 12345 违反了第一条规则,因为 'a' 与 'b' 一起出售。这是总体思路。

【问题讨论】:

在第一个表中是否会有一行表示“a 不能与 b 一起出售”,另一行表示“b 不能与 a 一起出售”? 【参考方案1】:
SELECT * FROM orders ord1, orders ord2, conditions con 
WHERE ord1.trans = ord2.trans 
AND ord1.item = con.Product1 AND ord2.item = con.Product2

【讨论】:

【参考方案2】:

我认为这是一种解决方案 将第一个表命名为 INCOMPAT,将第二个表命名为 ORDERS。 下面的查询将为您提供结果,但是在您的实际数据库中,您可能需要进行一些更改:

select o1.item + '@' + o2.item
from orders o1 full join  orders o2 on o1.orderid = o2.orderid
where exists (select * from incompat i where o1.item + '@' + o2.item = i.col1 + '@' + i.col2)

【讨论】:

【参考方案3】:

您可以通过按 id 加入交易来列出交易中所有可能的交易对。然后检查是否有任何一对违反规则

select distinct a.id
from transactions a
join transactions b on a.id = b.id and a.line_num <> b.line_num
join inappropriates c on a.item = c.col1 and b.item = c.col2;

【讨论】:

【参考方案4】:

如何在表 2 上使用自全连接,以获取每个订单中的所有组合。然后简单地将其内连接到表 1。

select * into #t1 from
(
    select 'a' as col1, 'b' as col2
    union
    select 'a' as col1, 'h' as col2
    union
    select 'a' as col1, 'd' as col2
) q


select * into #t2 from
(
select 1 as trans, 1 as line, 'a' as item
union
select 1 as trans, 2 as line, 'b' as item
union
select 1 as trans, 3 as line, 'a' as item
union
select 2 as trans, 1 as line, 'z' as item
union
select 2 as trans, 2 as line, 'f' as item
) q

select o.* from #t1 as v
inner join
(
    select distinct a.trans, a.item as item1, b.item as item2
    from #t2 as a
    full join #t2 as b on a.trans = b.trans and a.line <> b.line
) as o on v.col1 = o.item1 and v.col2 = o.item2

【讨论】:

【参考方案5】:

简单,只需使用 EXISTS 子句即可。

SELECT
  COUNT(*) 
FROM 
  Trans AS Trans1 
JOIN Trans AS Trans2 ON 
  Trans1.transNb = Trans2.transNb 
WHERE CONCAT(Trans1.item, '|', Trans2.item) IN 
  (SELECT CONCAT(item1, '|', item2) FROM xCombination) 

如果 COUNT 不为 0,则您的订单组合无效。

基本上,我们使用 Trans1 和 Trans2 以相同顺序对所有项目进行笛卡尔积。然后,我们用分隔符连接一个字符串中两个项目的每个组合。如果可以在 xCombination 表中找到一个字符串,那么该顺序就有问题。

这是SQL Fiddle。

【讨论】:

这可能与我最终所做的有 70% 的相似性。这是一个很好的开始。虽然有几个问题 - 首先是这会计算 2 个错误,实际上有 1 个。我想这意味着它会重复计算所有内容,这可以通过除以 2 来解决,但它仍然有点混乱.. 第二,更重要的是,如果有超过 2 个交易号,这将不起作用。 IRL 还有很多。有时90+。我喜欢连接方法,但我可能必须使用 FOR XML 将行连接在一起,而无需进行连接或枢轴 订单 12345 有 2 个错误,因为有两倍组合 ab。另外你为什么说它不适用于多个交易号? select com.id, a.transNb, a.item, a.t2 from (SELECT trans1.transNb, trans1.item, trans2.item as t2 FROM Trans AS Trans1 JOIN Trans AS Trans2 ON Trans1 .transNb = Trans2.transNb) a.item = com.item1 和 a.t2 = com.item2 上的左连接 xCombination com,其中 com.item1 不为空【参考方案6】:

这里是 Select 查询:

创建表和插入值的代码

Create Table InvalidCombos(item1 int, item2 int)

Create Table TransactionInfo(transactionId int, item int)

Insert Into InvalidCombos Values(1,2), (1,8), (1,4), (2,6), (2,26), (3,26), (3,4), (3,2)

Insert Into TransactionInfo Values(12345,1), (12345,2), (45678,26), (45678,6)

这是带有结果的 select 语句:

Select ic.item1, ic.item2, transinfo.transactionId From invalidcombos ic 
  INNER JOIN ( 
    Select ti1.transactionId, ti1.item as item1, ti2.item as item2 
      From TransactionInfo ti1 
      LEFT JOIN TransactionInfo ti2 ON ti1.transactionid = ti2.transactionid 
      and ti1.item <> ti2.item
    )
    transinfo ON (transinfo.item1 = ic.item1 AND transinfo.item2 = ic.item2)

【讨论】:

以上是关于基于多个条件的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

where条件放在子SQL语句中是否查询速度更快?

返回基于多个条件 SQL、MS Access 的非不同行

SQL多个条件模糊查询问题。。。

SQL多个条件查询语句

Python中SQL语句当查询多个条件,如果条件为空,则不加入查询条件;如果条件不为空,则加入查询条件

基于连续条件的 SQL 查询计数