SQL Select - добавление поля в Select меняет результаты - PullRequest
1 голос
/ 26 февраля 2011

Я озадачен этой проблемой SQL, которая, как я подозреваю, будет легкой для кого-то.

У меня есть таблица, которая содержит строки, представляющие несколько ежедневных списков ранжированных элементов.Уместны следующие поля: ID, ListID, ItemID, ItemName, ItemRank, Date.

У меня есть запрос, который возвращает элементы, которые были в списке вчера, но не сегодня (Items Off List), следующим образом:

Select ItemID, ListID, ItemName, convert(varchar(10),MAX(date),101) as date, COUNT(ItemName) as days_on_list 
From Table 
Group By ItemID, ListID, ItemName
Having Max(date) = DATEADD("d",-1,convert(varchar(10),getdate(),101)) and ListID = 1
Order By ListID, ItemName, COUNT(ItemName)

В основном я ищу записи, где максимальная дата вчерашнего дня.Он работает нормально и показывает количество дней, в течение которых каждый элемент ранее был в списке (хотя это не обязательно последовательно, но пока это нормально).

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

Select ItemID, ListID, ItemName, ranking, convert(varchar(10),MAX(date),101) as date, COUNT(ItemName) as days_on_list 
From Table
Group By ItemID, ListID, ItemName, ranking
Having Max(date) = DATEADD("d",-1,convert(varchar(10),getdate(),101)) and ListID = 1
Order By ListID, ItemName, ranking, COUNT(ItemName)

Это возвращает намного больше записей, чем предыдущий запрос, поэтому что-то не так с ним.Я хочу такое же количество записей, но с учетом рейтинга.Я могу получить ранг, выполнив самостоятельное объединение с подзапросом и получив записи, где ItemID встречается вчера, а не сегодня - но тогда я больше не знаю, как получить Count.

Оценка заранееза любую помощь с этим.

======== решено ==============

Select ItemID, ListID, ItemName, ranking, convert(varchar(10),MAX(date),101) as date, (Select COUNT(ItemName) From Table T3 Where T3.ItemID = T.ItemID and T3.ListID = 1) as days_on_list
from Table T
Where date = DATEADD("d",-1,convert(varchar(10),getdate(),101)) and ListID = 1 and T.ItemID Not In
(select T.ItemID from Table T
    join Table T2 on T.ItemID = T2.ItemID and T.ListID = T2.ListID
    where T.date = DATEADD("d",-1,convert(varchar(10),getdate(),101)) and T2.date = convert
(varchar(10),getdate(),101) and T.ListID = 1)
Group by ItemID, ListID, ItemName, ranking

По сути, то, что я сделал, былосоздайте подзапрос, который находит все элементы, которые появляются в оба дня, и находит элементы, которые появились вчера, но не входят в набор элементов, которые появились оба дня.Тогда я смог сделать агрегатную функцию и группировку правильно.Я НЕ удивлюсь, если это будет более запутанным, чем необходимо, но я понимаю это и могу изменить его по мере необходимости, и производительность не кажется проблемой.

Спасибо всем еще раз!

Ответы [ 4 ]

2 голосов
/ 26 февраля 2011

Проблема, вероятно, в том, что ранжирование отличается для элементов, которые в первом вопросе будут сгруппированы.

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

Если дело обстоит именно так, и вы все еще хотите иметь одинаковое количество строк, вы должны включить ранжирование после группировки с вопросом об упаковке, а затем вам также нужно решить, хотите ли вы минимальное или максимальное ранжирование из соответствующих строк.

1 голос
/ 26 февраля 2011

Вы можете рассчитать количество без использования Group By с помощью предложения Over.

With Items As
    (
    Select ItemID, ListID, ItemName, Ranking, [Date]
        , Row_Number() Over( Partition By ItemID, ListID, ItemName Order By [Date] Desc ) As Num
        , Count(ItemName) Over ( Partition By ItemId, ListId, ItemName ) As DaysOnList
    From Table As T
    Where T.[Date] = DateAdd(d, -1, CURRENT_TIMESTAMP) 
        And Not Exists  (
                        Select 1
                        From Table As T2
                        Where T2.ItemID = T.ItemID
                            And T2.ListId = T.ListId
                            And T2.[Date] > T.[Date]
                        )
    )
Select ItemID, ListID, ItemName, LastDate, Ranking
From Items
Where Num = 1
Order By ListID, ItemName, DaysOnList
1 голос
/ 26 февраля 2011

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

Мне нужно будет просмотреть примерный набор данных и примерные желаемые значения, прежде чем предлагать решение для запроса.

0 голосов
/ 26 февраля 2011

Я не уверен, что это ваша проблема, и мне хотелось бы, чтобы у меня была репутация комментировать это, но необходим ли пункт «ранжирование» в группе по утверждению? Учитывая этот контекст, это не выглядит так, как должно быть.

...