Тестирование на существование с использованием SELECT WHERE HAVING и NOT HAVING в сгруппированном подмножестве - PullRequest
0 голосов
/ 30 декабря 2010

РЕДАКТИРОВАТЬ: образец ввода / вывода в конце.

У меня есть данные, на которые мне нужно сосчитать +1, если определенное условие существует или другое условие не существует. Я использую SQL Server 2008.

Я уничтожил следующий упрощенный образец XML во временной таблице и проверил его:

  <product type="1">
    <param type="1">
      <item mode="0" weight="1" />
    </param>
    <param type="2">
      <item mode="1" weight="1" />
      <item mode="0" weight="0.1" />
    </param>
    <param type="3">
      <item mode="1" weight="0.75" />
      <item mode="1" weight="0.25" />
    </param>
  </product>

В проверке действует следующее правило:

Для каждого типа продукта, для каждого типа параметра, режим может быть 0 & (1 || 2). В другими словами, может быть 0 (s), но тогда 1 или 2 требуются, или там может быть только 1 (s) или 2 (s). Там не может быть только 0, и не может быть 1 и 2с.

Единственная часть, которую я не понял, это как определить, есть ли только 0. Это похоже на проблему "не иметь".

Код подтверждения (для этой части):

WITH t1 AS (
    SELECT      SUM(t.ParamWeight) AS S, COUNT(1) AS C, 
                t.ProductTypeID, t.ParamTypeID, t.Mode
    FROM        @t AS t
    GROUP BY    t.ProductTypeID, t.ParamTypeID, t.Mode
),
    ...
    UNION ALL           
    SELECT      TOP (1) 1   -- only mode 0 & (1 || 2) is allowed
    FROM        t1
    WHERE       t1.Mode IN (1, 2)
    GROUP BY    t1.ProductTypeID, t1.ParamTypeID
    HAVING      COUNT(1) > 1
    UNION ALL
    ...
)
SELECT      @C = COUNT(1)
FROM        t2

Это покажет, если какие-либо режимы 1 и 2 смешаны, но не если группа содержит только 0. Я уверен, что есть простое решение, но оно уклоняется от меня прямо сейчас.

EDIT:

Я подумал о "чите", которая отлично работает. Я добавил следующее к вышесказанному:

SELECT      TOP (1) 1   -- only mode 0 & (null || 1 || 2) is allowed
FROM        t1
GROUP BY        t1.ProductTypeID, t1.ParamTypeID
HAVING      SUM(t1.Mode) = 0

Однако я все еще хотел бы знать, как это сделать без обмана.

ОБРАЗЕЦ

Zero  One  Two  Result
1     0    0    False
0     1    1    False
1     1    1    False
0     1    0    True
0     0    1    True
1     1    0    True
1     0    1    True

1 Ответ

2 голосов
/ 30 декабря 2010

Ну, вы можете написать следующий запрос:

SELECT ProductTypeID,ParamTypeID,MIN(Mode) as Has0,MAX(Mode) as M1or2,MAX(CASE WHEN Mode=1 THEN 1 ELSE 0 END) as M1
from @t
group by ProductTypeID,ParamTypeID

Я думаю, что вы можете просто использовать эти 3 столбца, чтобы ответить на ваш запрос.Если Has0 = 0, то есть значение режима 0, поэтому вам нужно, чтобы M1or2 было больше 0 (если я правильно понимаю).

Вы также можете проверить, что если M1or2 = 2,тогда (я думаю) вы хотите, чтобы M1 было равно 0 (строки в режиме 1 не были найдены, если была найдена строка в режиме 2).

Мне кажется, я правильно прочитал ваше описание.Если нет, то это может помочь, если вы добавите несколько примеров «разрешенных» и «запрещенных» комбинаций.


SELECT ProductTypeID,ParamTypeID,CASE
    WHEN M1OrM2 = 2 And M1 = 1 THEN 0 /* Have both mode 2 and mode 1. Can ignore whether it has any Mode 0 */
    WHEN Has0 = 0 AND M1OrM2 = 0 THEN 0 /* Has a mode 0 and no M1 or M2 */
    ELSE 1 END /* All other combinations are allowed */
FROM (
SELECT ProductTypeID,ParamTypeID,MIN(Mode) as Has0,MAX(Mode) as M1or2,MAX(CASE WHEN Mode=1 THEN 1 ELSE 0 END) as M1
from @t
group by ProductTypeID,ParamTypeID
) t
...