2016-04-08 2 views
2

У меня есть таблица продуктов и таблица виджетов.Рефакторинг подзапроса в операторе select для соединения

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

Виджеты могут быть помечены как expired, что означает, что они не могут быть добавлены ни к каким новым продуктам.

схемы и примеры данных в следующих sqlFiddle -

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

  1. Виджет не должен быть показаны если он отмечен как истек.
  2. В качестве исключения из приведенного выше правила. Если виджет отмечен как истек, но уже связан с продуктом, он должен быть показан.
  3. Если виджет уже связан с продуктом, он должен быть помечен как 'selected'

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

select 
    data.WidgetName, 
    data.expired, 
    case 
     when data.ID in (select data_id from Widget_link where productId = 1) 
     then 1 
     else 0 
    end as selected 
from Widget_data data 
left outer join Widget_link link 
    on data.ID = link.data_id and data.expired = 1 
where (data.expired = 0 or (data.expired = 1 and link.productId = 1)) 

Я хотел бы найти способ рефакторинга подзапроса в пределах выделенной части запроса на какое-то соединение. Я пытаюсь создать представление, которое я могу фильтровать, используя только предложение where, вместо того, чтобы иметь productId в двух местах. Это возможно?

ответ

3

При упрощении ваш запрос может быть оценен только на основе JOIN, как показано ниже, и нет необходимости в внутреннем запросе.

select data.WidgetName, 
    case when link.id is not null then 1 else 0 end as selected 
from Widget_data data 
left outer join Widget_link link 
    on data.ID = link.data_id and link.productId = 1 
where data.expired=0 or link.id is not null 

Demo SQL fiddle

+0

Это, кажется, хорошо работает - Спасибо! – John

0

Вы можете использовать SQL CTE (Common Table Expression) для покрытия результатов из отобранного списка и использовать в одном операторе SQL

Вы можете даже создать SQL statements with multiple CTE's в коде

То, что я предлагаю, можно суммировать визуально следующим образом:

WITH cte AS (
    SELECT ..... FROM ..... 
), 
other_cte AS (
    SELECT ..... FROM ..... 
) 
SELECT * 
FROM cte 
INNER JOIN other_cte ON...