如何连接可变数量的条件匹配的表

时间:2014-07-08 17:35:21

标签: sql join pivot

我有两个表,tblPerson和tblOffer。人员表详细说明了他们目前拥有哪些产品。这些优惠有多个标准,我们是否应该建议一个人获得新产品。

我试图根据tblOffer中的多个标准加入这些标准,但是要坚持确保判断所有选定的标准,而不仅仅是其中任何标准。例如,我的表格中有一些字段。

tblPerson
pkPersonId
HasCreditCard
HasEmail
HasLoan

tblOffer
pkOfferId
NeedsCreditCard
NeedsEmail
NeedsLoan

示例数据:

tblPerson
1, 0, 0, 1
2, 0, 1, 0
3, 0, 0, 0

tblOffer
100, 1, 0, 1
200, 0, 0, 1
300, 1, 1, 0

我试图为包含Offer 300的人1返回结果,Person 2获得100和200的优惠,而Person 3获得100,200和300的优惠。

我在两个表之间尝试了Cross APPLY,然后使用我的WHERE子句说:

SELECT * FROM tblPerson prs
        CROSS JOIN tblMrmOffer ofr
    WHERE prs.pkPersonId = @PersonId AND (
            (prs.HasEmail = 0 AND ofr.NeedsEmail = 1) OR 
            (prs.HasCreditCard = 0 AND ofr.NeedsCreditCard = 1) OR
            (prs.HasLoan = 0 AND ofr.NeedsLoan = 1))

如果任何选定的条件为真,这将给我一行但不限于设置了所有选定条件的行。例如,如果此人需要信用卡或电子邮件,则提议300将匹配,但如果他们需要两者,则不一定。我试图将其作为Cross Tab Pivot来解决,但不清楚如何加入这个。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

如果您试图制作它以便只显示某个人需要该优惠中的每个项目的优惠,但如果该人已经拥有至少一件事物,则优惠被取消资格,那么这里是一些SQL尝试。每个AND条件所说的是我们想要取消该人已经在要约中有项目的情况。

SELECT * FROM tblPerson prs
    CROSS JOIN tblMrmOffer ofr
WHERE prs.pkPersonId = @PersonId
  AND
    NOT (prs.HasEmail = 1 AND ofr.NeedsEmail = 1)
  AND
    NOT (prs.HasCreditCard = 1 AND ofr.NeedsCreditCard = 1)
  AND
    NOT (prs.HasLoan = 1 AND ofr.NeedsLoan = 1)

相反,如果您正在寻找优惠满足所有人需求的情况,那么这个SQL可能更适合你的小巷。具有case语句的理论是,如果条件是重要的(HasX = 0时就是这种情况),那么NeedsX的过滤器需要为1。否则,它只匹配NeedsX值(因此过滤器不会做任何事情)。

SELECT * FROM tblPerson prs
    CROSS JOIN tblMrmOffer ofr
WHERE prs.pkPersonId = @PersonId
  AND
      (
        ofr.NeedsEmail
        =
        CASE
          WHEN prs.HasEmail = 0
          THEN 1
          ELSE ofr.NeedsEmail
        END
      )
  AND
      (
        ofr.NeedsCreditCard
        =
        CASE
          WHEN prs.HasCreditCard = 0
          THEN 1
          ELSE ofr.NeedsCreditCard
        END
      )
  AND
      (
        ofr.NeedsLoan
        =
        CASE
          WHEN prs.HasLoan = 0
          THEN 1
          ELSE ofr.NeedsLoan
        END
      )

如果你想变得非常花哨,你可以在你的选择声明中列出一个排名,将符合个人需求的案例排列在与满足某些用户未满足需求相匹配的案例之上。对于这个,它看起来像这样,首先优先匹配完美匹配,然后优先匹配第二(在匹配良好的匹配,提供更多项目的那些),然后在这些类别中,最先提供最新优惠:

SELECT
  ...
  DENSE_RANK() OVER (
    PARTITION BY prs.pkPersonID
    ORDER BY
      CASE
        WHEN <logic from 2nd SQL above>
        THEN 1
        WHEN <logic from 1st SQL above>
        THEN ofr.NeedsEmail + ofr.NeedsCreditCard + ofr.NeedsLoan
        ELSE NULL
      END,
      ofr.pkOfferId DESC
  ) AS Order
  ...