Исключить записи из одной таблицы на основе количества в объединенной таблице - PullRequest
2 голосов
/ 15 января 2010

У меня есть две таблицы: купоны и ответы.

Таблица купонов включает такие поля, как:

  • VendorID [ключ]
  • CouponID [ключ]
  • CouponDescription

Таблица ответов включает в себя такие поля, как:

  • RespondentID [ключ]
  • CouponID [ключ]
  • (VendorID не повторяется в этой таблице.)
  • Принято [истина / ложь]
  • Отклонено [true / false]
  • Рейтинг [от 1 до 5]

Когда кто-то принимает купон, он в конечном итоге оценивает его в таблице ответов. Аналогичным образом, когда кто-то отклоняет купон, отказ появляется в таблице ответов.

При получении списка доступных купонов из таблицы «Купоны» я бы хотел исключить поставщиков, которые ранее получали два или более отказа от респондента. Например, если RespondentID 3 ранее отклонил два или более купонов от Продавца 47, все купоны от Продавца 47 больше не будут отображаться для RespondentID 3.

Две вещи затрудняют новичка в SQL, как я.

  1. Во-первых, как написать подзапрос, который подсчитывает отклонения от от конкретного поставщика и от от конкретного респондента.

  2. Второй способ - как присоединить (так сказать) таблицу Response к таблице Coupons так, чтобы подзапрос таблицы Response основывал свой результат на RespondentID (который находится в таблице Responses) и VendorID (который не в таблице ответов и должен быть определен на основе CouponID (который находится в обеих таблицах).

Спасибо за вашу помощь. Это всегда ценится.

Ответы [ 3 ]

1 голос
/ 15 января 2010

Может быть что-то вроде этого:

   SELECT * FROM Coupons 
     WHERE VendorId NOT IN (
        SELECT C.VendorId 
          FROM Responses R JOIN Coupons C ON R.CouponId = C.CouponId
          WHERE R.RespondentID = 3 AND R.Rejected = True
          GROUP BY C.VendorId
          HAVING SUM(R.Rejected) > 2
     )

Я никогда не использовал HAVING без включения его значения в SELECT, но я думаю, что это может сработать. Кроме того, не уверен насчет типа данных Отклонено, вероятно, SUM () не будет работать.

0 голосов
/ 15 января 2010

Вот что я придумала ...

SELECT
   * 
   FROM Coupons C 
   WHERE C.OriginatorID NOT IN (
      SELECT 
         DISTINCT C.OriginatorID 
         FROM Responses R  
         INNER JOIN Coupons C ON C.CouponID = R.CouponID 
         WHERE C.OriginatorID IN  (
            SELECT Originators FROM (
               SELECT C.OriginatorID As Originators, Sum(R.Rejected) AS Rejections 
               FROM Responses R INNER JOIN Coupons C ON C.CouponID = R.CouponID
               WHERE R.RespondentID = 1
               GROUP BY C.OriginatorID
            ) AS RejectionTally 
            WHERE Rejections > 1
         )
   )

У него есть недостаток, заключающийся в дополнительном встроенном SELECT, но похоже, что большая часть снижения производительности происходит в тот момент, когда я пытаюсь исключить определенные идентификаторы OriginatorID из таблицы Coupons. Например, вручную введите исключение, например ...

SELECT * FROM Coupons WHERE OriginatorID <> 10

имеет тот же эффект. В тестовой таблице из 50 строк время обработки равно .27 с, в отличие от неограниченного запроса, который имеет время обработки .08 с.

Дополнительное встраивание происходит из-за того, что мне нужен один столбец для внешнего NOT IN (то есть идентификатора OriginatorID, который я пытаюсь исключить). Это означало, что мне сначала нужно было создать SUM, затем изолировать записи, SUM которых меньше критерия (1), а затем исключить эти записи.

0 голосов
/ 15 января 2010

ОК, это длинный путь, и я не уверен, что этот запрос действительно будет выполняться, но я думаю, что ключ заключается в том, что вам нужно включить таблицу Coupon дважды Попробуйте это (я думаю, однако, что where недопустимо так):

select c.CouponID, c.CouponDescription,
       (select count(r.CouponID)
          from Responses r
         inner join Coupons c2 on c2.CouponID = r.CouponID
         where r.RespondentID = 3
           and r.Rejected = true
           and c2.VendorID = c.VendorID) as countRejections

  from Coupons c
 where countRejections < 2
...