Я нашел вопрос, который был очень похож на этого, но использующие функции, которые кажутся эксклюзивными 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
Вызовите 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
Только одна запись на пользователя, независимо от того, сколько строк на пользователя имеет одно и то же максимальное значение.
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
Попробуйте это ... Я уверен, что это единственный способ действительно следить за тем, чтобы вы получили один ряд на пользователя.
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)
Есть несколько способов сделать это, взгляните на это Включая связанные с колонкой значения Показано несколько методов, включая разницу в производительности
Вот один пример
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