避免笛卡尔积检查对

时间:2017-01-12 15:22:15

标签: sql sql-server cartesian-product

我在SQL Server 2014中有两个表:

  1. 表A包含三列:Group,Proc和Date
  2. 表B包含四列:Proc1,Proc2,Start,End
  3. 表B是如果组中的最小日期在开始和结束之间,则不应出现在表A的同一组中的过程对的列表。我试图找到表A中违反此规则的组,但问题是表A有60M组,每组最多100行,表B有65000对。

    其他deets:

    • 结束可以为NULL
    • Proc1和Proc2总是长度为5个字符,但Proc可以是任意长度

    我的策略是

    1. 对于A中的每个组,获取最小日期并将所有由逗号分隔的Proc的唯一值(该字段从不包含逗号)填充到新字段Procs。使用Group MinDate Procs。

    2. 产生表C.
    3. 获取C和B的笛卡尔积,其中(i)开始和结束之间的MinDate(或者>开始和结束为NULL)和(ii)如果我替换Proc1的实例,则Procs的长度减少10和其中的Proc2是空字符串。

    4. 此过程有效(在数据的子集上),但我正在寻找有关如何将其扩展到完整数据集的建议。

      如果您需要任何其他详细信息,请与我们联系。谢谢!

1 个答案:

答案 0 :(得分:1)

如果我理解正确,你可以用连接来做到这一点。如果b中的每一行都有唯一标识符,那将会有所帮助。

方法是将表连接在一起,然后计算b中每行的违规次数:

select a.group, b.id, count(distinct a.proc) as num_procs
from a join
     b
     on a.proc in (b.proc1, b.proc2) and
        a.date between b1.start and coalesce(b1.end, getdate())
group by a.group, b.id
having count(distinct a.proc) = 2;

如果您没有b.id,则可以使用四列来标识每一行。

proc长度的具体数据问题是一个单独的问题。您应该修复数据,以便两个表之间匹配的字段实际上具有相同的类型。