Проблема с тем, как создать оператор выбора на основе условий - PullRequest
1 голос
/ 09 ноября 2011

В поисках некоторых указаний о том, какие варианты мне следует рассмотреть для решения следующей проблемы создания оператора select (SQL SERVER) на основе условий:

ПРИМЕЧАНИЕ: упрощение актуальной проблемы

Если у меня есть две таблицы, каждая с полем, которое мне нужно использовать ПРИМЕР:

CUSTOMER.CUSTOMER_ID
PRODUCT.PRODUCT_ID

У меня есть еще 2 таблицы, в которых указаны специальные цены на товары на основе этих двух полей. Пример:

CUSTOMER_PRICING 
***************************************
* CUSTOMER_ID  * PRODUCT_ID  * PRICE  *
*                                     *
*     ABC      *    100      *  5.00  *
***************************************

MARKET_PRICING 
***************************************
* CUSTOMER_ID  * PRODUCT_ID  * PRICE  *
*                                     *
*     ACME      *    200      *  7.00 *
***************************************

Для каждого CUSTOMER.CUSTOMER_ID и PRODUCT.PRODUCT_ID я хочу присоединиться к записям CUSTOMER_PRICING и MARKET_PRICING, используя внешнее левое соединение. Но условия только если

А) поле ЦЕНА не является нулевым

B) и если CUSTOMER_ID / PRODUCT_ID существует в обоих, я хочу получить запись только из CUSTOMER_PRICE

Что-то вроде:

IF EXISTS (SELECT C.CUSTOMER_ID, P.PRODUCT_ID FROM CUSTOMER C, PRODUCT P 
           WHERE C.CUSTOMER_ID, P.PRODUCT_ID IN 
           (SELECT PRICE FROM CUSTOMER_PRICE WHERE PRICE IS NOT NULL))
ELSE IF EXISTS 
          (SELECT C.CUSTOMER_ID, P.PRODUCT_ID FROM CUSTOMER C, PRODUCT P 
           WHERE C.CUSTOMER_ID, P.PRODUCT_ID IN 
           (SELECT PRICE FROM MARKET_PRICE WHERE PRICE IS NOT NULL))

***, тогда как-нибудь объедините эти результаты .....

Есть предложения?

Ответы [ 4 ]

1 голос
/ 10 ноября 2011

Создание представления CMPricing значительно упростит эту ситуацию.

CREATE VIEW CMPricing AS<br> SELECT t1.CUSTOMER_ID, t1.PRODUCT_ID, t1.PRICE AS CUSTOMER_PRICE t2.PRICE AS MARKET_PRICE<br> FROM CUSTOMER_PRICING t1 INNER JOIN MARKET_PRICING t2 ON t1.CUSTOMER_ID = t2.CUSTOMER_ID AND t1.PRODUCT_ID = t2.PRODUCT_ID<br> WHERE t1.PRICE IS NOT NULL AND t2.PRICE IS NOT NULL Затем вы запрашиваете это представление, чтобы получить то, что вы хотите.

Это представление будет содержать только те данные, которые являются общими для обеих таблиц "PRICE" , где оба значения "PRICE" не равны нулю. По сути, это представление делает фильтрацию за вас, что, в свою очередь, облегчает понимание и понимание ваших запросов с другими таблицами данных.

1 голос
/ 09 ноября 2011

Я думаю, что нашел решение.Я уверен, что эксперт по SQL мог бы придумать что-то лучше, но это должно заставить вас двигаться:

WITH CTE AS
(
    SELECT C.CUSTOMER_ID, C.PRODUCT_ID, C.CUSTOMER_PRICE as [PRICE], 1 as [T]
    FROM CUSTOMER_PRICE C WHERE C.CUSTOMER_PRICE IS NOT NULL
    UNION
    SELECT P.CUSTOMER_ID, P.PRODUCT_ID,P.MARKET_PRICE as [PRICE], 2 as [T]
    FROM MARKET_PRICE P WHERE P.MARKET_PRICE IS NOT NULL
)
select CUSTOMER_ID,PRODUCT_ID,
    (
        SELECT TOP (1) PRICE FROM CTE i WHERE i.CUSTOMER_ID = o.CUSTOMER_ID AND i.PRODUCT_ID = o.PRODUCT_ID
        ORDER BY T
    ) as [PRICE]
from CTE o
GROUP BY CUSTOMER_ID,PRODUCT_ID

Это даст вам четкий список идентификаторов клиентов, идентификаторов продуктов и цен;в пользу CUSTOMER_PRICE цена.

РЕДАКТИРОВАТЬ Это будет работать только с базами данных SQL 2008 и выше.Он использует Общих табличных выражений , которые являются новыми конструкциями до 2008 года.

ОБНОВЛЕНИЕ Исправлено предложение where.

1 голос
/ 09 ноября 2011

Вы можете объединить перекрестное произведение CUSTOMER и PRODUCT с обоими CUSTOMER_PRICING и MARKET_PRICING, отфильтровав строки, в которых оба значения CUSTOMER_PRICING.PRICE и MARKET_PRICING.PRICE равны NULL. Это может выглядеть примерно так:

SELECT
  c.CUSTOMER_ID,
  p.PRODUCT_ID,
  COALESCE(cp.PRICE, mp.PRICE) AS PRICE
FROM CUSTOMER c
  CROSS JOIN PRODUCT p
  LEFT JOIN CUSTOMER_PRICING cp ON cp.CUSTOMER_ID = c.CUSTOMER_ID AND cp.PRODUCT_ID = p.PRODUCT_ID
  LEFT JOIN MARKET_PRICING   mp ON mp.CUSTOMER_ID = c.CUSTOMER_ID AND mp.PRODUCT_ID = p.PRODUCT_ID
WHERE cp.PRICE IS NOT NULL OR mp.PRICE IS NOT NULL
-- Or, put differently:
-- WHERE NOT (cp.PRICE IS NULL AND mp.PRICE IS NULL)
0 голосов
/ 09 ноября 2011

Если вы используете ORACLE, вы должны использовать объединение, чтобы удалить повторяющиеся строки и сделать 2 отдельных запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...