Выберите строку, которая сделала, чтобы Max оценил за столбец в SQL Server

Я нашел вопрос, который был очень похож на этого, но использующие функции, которые кажутся эксклюзивными Oracle. Я надеюсь делать это в SQL Server.

У меня есть таблица как это:

MyTable
--------------------
MyTableID  INT  PK
UserID     INT
Counter    INT

У каждого пользователя может быть несколько строк с различными значениями для Counter в каждой строке. Я должен найти строки с самым высоким Counter значение для каждого пользователя.

Как я могу сделать это в SQL Server 2005?

Лучшим, который я могу придумать, является запрос возвраты MAX(Counter) для каждого UserID, но мне нужна вся строка из-за других данных в этой таблице, не показанной в моем определении таблицы для пользы простоты.

Править: Это привлекло мое внимание из некоторых ответов в этом сообщении, что я забыл важную деталь. Возможно иметь 2 + строки, где UserID может сделать, чтобы тот же МАКС противостоял значению. Пример ниже обновленного для того, каковы ожидаемые данные/вывод должны быть.

С этими данными:

MyTableID   UserID   Counter
---------   -------  --------
1           1         4
2           1         7
3           4         3
4           11        9
5           11        3
6           4         6
...
9           11        9

Я хочу эти результаты для дубликата МАКС. значения, выбор, первое происшествие в любом SQL-сервере порядка выбирает их. То, какие строки возвращаются, не важно в этом случае, пока пары Идентификатора пользователя/Счетчика отличны:

MyTableID   UserID    Counter
---------   -------   --------
2           1         7
4           11        9
6           4         6
6
задан Dan Herbert 19 January 2010 в 22:19
поделиться

4 ответа

Вызовите remureUpdates в LocationManager, передав прослушиватель местоположения.

-121--4565833-

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

Я выполнил некоторые тесты с файлом 100MB, сохраненным на сетевом диске, и скорость полностью зависела от того, как быстро он может читать файл. Если файл был буферизован в Windows, поиск всего файла занял менее 3 секунд. В противном случае это может занять от 7 секунд до 60 секунд, в зависимости от скорости сети.

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

public static int FindInFile(string fileName, string value)
{   // returns complement of number of characters in file if not found
    // else returns index where value found
    int index = 0;
    using (System.IO.StreamReader reader = new System.IO.StreamReader(fileName))
    {
        if (String.IsNullOrEmpty(value))
            return 0;
        StringSearch valueSearch = new StringSearch(value);
        int readChar;
        while ((readChar = reader.Read()) >= 0)
        {
            ++index;
            if (valueSearch.Found(readChar))
                return index - value.Length;
        }
    }
    return ~index;
}
public class StringSearch
{   // Call Found one character at a time until string found
    private readonly string value;
    private readonly List<int> indexList = new List<int>();
    public StringSearch(string value)
    {
        this.value = value;
    }
    public bool Found(int nextChar)
    {
        for (int index = 0; index < indexList.Count; )
        {
            int valueIndex = indexList[index];
            if (value[valueIndex] == nextChar)
            {
                ++valueIndex;
                if (valueIndex == value.Length)
                {
                    indexList[index] = indexList[indexList.Count - 1];
                    indexList.RemoveAt(indexList.Count - 1);
                    return true;
                }
                else
                {
                    indexList[index] = valueIndex;
                    ++index;
                }
            }
            else
            {   // next char does not match
                indexList[index] = indexList[indexList.Count - 1];
                indexList.RemoveAt(indexList.Count - 1);
            }
        }
        if (value[0] == nextChar)
        {
            if (value.Length == 1)
                return true;
            indexList.Add(1);
        }
        return false;
    }
    public void Reset()
    {
        indexList.Clear();
    }
}
-121--2695403-

Для этого случая я хотел бы использовать общее табличное выражение с подходящей функцией ROW_NUMBER ():

WITH MaxPerUser AS
(
  SELECT 
    MyTableID, UserID, Counter,
    ROW_NUMBER() OVER(PARTITION BY userid ORDER BY Counter DESC) AS 'RowNumber'
  FROM dbo.MyTable
)
SELECT MyTableID, UserID, Counter 
FROM MaxPerUser
WHERE RowNumber = 1

THAT разбивает данные по идентификатору пользователя, упорядочивает их по счетчику (по убыванию) для каждого пользователя, а затем помечает каждую из строк, начиная с 1 для каждого пользователя. Выберите только те строки с 1 для числа строк, и у вас есть максимальные значения для каждого пользователя.

Это так просто: -) И я получаю результаты примерно так:

MyTableID   UserID  Counter  
   2           1        7   
   6           4        6
   4          11        9

Только одна запись на пользователя, независимо от того, сколько строк на пользователя имеет одно и то же максимальное значение.

9
ответ дан 9 December 2019 в 20:43
поделиться
select m.* 
from MyTable m
inner join (
    select UserID, max(Counter) as MaxCounter
    from MyTable
    group by UserID
) mm on m.UserID = mm.UserID and m.Counter = mm.MaxCounter
0
ответ дан 9 December 2019 в 20:43
поделиться

Попробуйте это ... Я уверен, что это единственный способ действительно следить за тем, чтобы вы получили один ряд на пользователя.

SELECT MT.* 
FROM    MyTable MT
    INNER JOIN (
        SELECT  MAX(MID.MyTableId) AS MaxMyTableId,
            MID.UserId
        FROM    MyTable MID
            INNER JOIN (
                SELECT  MAX(Counter) AS MaxCounter, UserId
                FROM    MyTable
                GROUP BY UserId
            ) AS MC
                ON (MID.UserId = MC.UserId
                    AND MID.Counter = MC.MaxCounter)
        GROUP BY MID.UserId
    ) AS MID
        ON (MID.UserId = MC.UserId
            AND MID.MyTableId = MC.MaxMyTableId)
0
ответ дан 9 December 2019 в 20:43
поделиться

Есть несколько способов сделать это, взгляните на это Включая связанные с колонкой значения Показано несколько методов, включая разницу в производительности

Вот один пример

select t1.*
from(
select UserID, max(counter) as MaxCount
from MyTable
group by UserID) t2
join MyTable t1 on t2.UserID =t1.UserID
and t1.counter = t2.counter
0
ответ дан 9 December 2019 в 20:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: