Требуется справка SQL: SELECT Таблица A объединяется с таблицей B (Макс или Ноль) - PullRequest
2 голосов
/ 20 апреля 2011

В таблице A (псевдоним ai) у меня есть список предметов. В таблице B (псевдоним aib) у меня есть история цен для всех элементов таблицы A, но не для всех элементов, для которых мне нужно выбрать NULL. Мне нужно выбрать предмет из таблицы A, это максимальная цена из таблицы B или NULL.

Вот что у меня есть, но оно не совсем работает, я получаю дубликаты записей, если таблица B имеет обширную историю цен.

Вот не совсем рабочий запрос:

SELECT *

FROM ItemGroup aig 

INNER JOIN Item ai ON ai.groupID = aig.ID 

LEFT JOIN Item_Prices aib ON ai.ID = aib.ItemID 

WHERE aig.ID = @groupID AND 
(aib.max_price = (SELECT MAX(price) AS highprice FROM Item_Prices 
  WHERE ItemID = ai.ID) 
  OR aib.price IS NULL) 

ORDER BY end_date

Все предложения приветствуются.

почтение,

Ray

Ответы [ 4 ]

1 голос
/ 20 апреля 2011

@ squillman почти прибил его.Оптимизировано:

SELECT GroupID      = aig.groupID     ,
       ItemID       = ai.ID as ItemID ,
       HighestPrice = aib.HighestPrice
FROM      Item        ai
left join ( select ItemID ,
                   HighestPrice = max(price)
            from Item_Prices
            group by ItemID
          ) aib on aib.ItemID = ai.ID
WHERE ai.groupID = @groupID
ORDER BY end_date

Если все, что вы просматриваете из таблицы ItemGroup, это идентификатор группы ... вам не нужна таблица: у вас уже есть groupID в таблице Item, поэтому ItemGroupне требуется, хотя вам нужно сохранить его, если вам нужны другие атрибуты из ItemGroup.Выход из ItemGroup не должен сильно влиять на план запроса: вам нужна не более одной группы, и, вероятно, ItemGroup имеет индекс покрытия для groupID.

distinct не требуется в подзапросе: group by ItemID делает подзапроснабор результатов уникален по ItemID.Это влияет на производительность: distinct означает, что движок должен гарантировать, что результирующий набор уникален.Надеюсь, оптимизатор поймет, что group by делает набор уникальным, и отбросит distinct, но я бы на это не рассчитывал.

1 голос
/ 20 апреля 2011

Рэй, ты просто используешь таблицу предметов, чтобы соединить две таблицы вместе?Если вам не нужно ничего из таблицы элементов для остальной части запроса, тогда это не является действительно необходимым.

Если все , которые вы действительно хотите сделать, это "выбрать элемент из таблицыA, это максимальная цена из таблицы B или NULL. "это может быть так же просто, как если бы Item_Prices.price допускает нулевые значения.

SELECT a.ItemName, MAX(b.price) AS 'MaxPrice' 
FROM Item AS a INNER JOIN Item_Prices AS b
ON a.groupID = b.ItemID
GROUP BY a.ItemName

Вот что в моей таблице Item_Prices

Contents of Item_Prices listing several null and duplicate values

Вот что втаблица моего товара

Contents of Item

Результат запроса:

Output from query

Вот представление дизайна моей таблицы товаров, groupIDявляется первичным ключом.

Design view of Item table with groupID as primary key

Вот представление конструкции моей таблицы Item_Prices, вы можете установить ItemID в качестве внешнего ключа

Design view of Item_Prices with itemID as primary key

Если вы хотите выбрать данные из отдельных таблиц, вам не нужна эта третья таблица, чтобы связать их для вас или чего-либо еще.Пока у них есть некоторый тип уникального идентификатора в Таблице A (первичный ключ) и соответствующий ключ (обычно внешний ключ) в Таблице B, который связывает вас, у вас все в порядке!

Если вы действительно намеревалисьчтобы получить эту третью таблицу для другого поля, тогда не обращайте внимания! Я просто хотел привести короткий пример, чтобы показать вам, что, потому что, когда я был на работе / в школе, я видел много людей, использующих третью таблицу для связистолы вместе, которые не имеют смысла, большую часть времени!

1 голос
/ 20 апреля 2011
SELECT *
FROM ItemGroup aig
INNER JOIN Item ai ON ai.groupID = aig.ID
LEFT OUTER JOIN (
    SELECT 
        ItemID,MAX(max_price)
    FROM Item_Prices
    GROUP BY ItemID
) aib ON ai.ID=aib.ItemID
WHERE aig.ID = @groupID
ORDER BY end_date

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

0 голосов
/ 20 апреля 2011
Select ...
From ItemGroup As AIG
    Join Item As AI
        On AI.ID = AIG.ID
Where AIG.Id = @groupId
    And Exists  (
                Select 1
                From Item_Prices As IP1
                    Join    (
                            Select IP2.ItemID, Max( IP2.Price ) As Price
                            From Item_Prices As IP2
                            Group By IP2.ItemId
                            ) As MaxPrices
                        On MaxPrices.ItemID = IP1.ItemID
                            And MaxPrices.Price = IP2.Price
                Where IP1.ItemID = AI.ID
                Union All
                Select 1
                From Item_Prices As IP1
                Where IP1.ItemID = AI.ID
                    And IP1.Price Is Null
                )
Order By End_Date
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...