Я модифицировал Get-WmiCustom Daniel Muscetta для поддержки передачи учетных данных.
Я знаю, что этот пост немного стар, надеюсь, это помогает кому-то другому.
# Define modified custom get-wmiobject for timeout with credential from http://blogs.msdn.com/b/dmuscett/archive/2009/05/27/get_2d00_wmicustom.aspx
Function Get-WmiCustom([string]$Class,[string]$ComputerName,[string]$Namespace = "root\cimv2",[int]$Timeout=15, [pscredential]$Credential)
{
$ConnectionOptions = new-object System.Management.ConnectionOptions
$EnumerationOptions = new-object System.Management.EnumerationOptions
if($Credential){
$ConnectionOptions.Username = $Credential.UserName;
$ConnectionOptions.SecurePassword = $Credential.Password;
}
$timeoutseconds = new-timespan -seconds $timeout
$EnumerationOptions.set_timeout($timeoutseconds)
$assembledpath = "\\$Computername\$Namespace"
#write-host $assembledpath -foregroundcolor yellow
$Scope = new-object System.Management.ManagementScope $assembledpath, $ConnectionOptions
$Scope.Connect()
$querystring = "SELECT * FROM " + $class
#write-host $querystring
$query = new-object System.Management.ObjectQuery $querystring
$searcher = new-object System.Management.ManagementObjectSearcher
$searcher.set_options($EnumerationOptions)
$searcher.Query = $querystring
$searcher.Scope = $Scope
trap { $_ } $result = $searcher.get()
return $result
}
Все, что вам нужно, - это предложение GROUP BY
с агрегатной функцией MAX
:
SELECT id, MAX(rev)
FROM YourTable
GROUP BY id
Я просто заметил, что вам нужен столбец content
.
Это очень распространенный вопрос в SQL: найти все данные для строки с некоторым максимальным значением в столбца на один идентификатор группы. Я много слышал о своей карьере. На самом деле, это был один из вопросов, которые я ответил в техническом интервью моей текущей работы.
На самом деле настолько распространено, что сообщество StackOverflow создало один тег только для решения таких вопросов: наибольшее-n-на-группу .
В принципе, у вас есть два подхода к решению этой проблемы:
group-identifier, max-value-in-group
Sub-query В этом подходе вы сначала найдете group-identifier, max-value-in-group
(уже решены выше) в подзапросе. Затем вы присоединяетесь к своей таблице к подзапросу с равенством как на group-identifier
, так и на max-value-in-group
:
SELECT a.id, a.rev, a.contents
FROM YourTable a
INNER JOIN (
SELECT id, MAX(rev) rev
FROM YourTable
GROUP BY id
) b ON a.id = b.id AND a.rev = b.rev
In этот подход, вы оставили присоединиться к таблице с собой. Равенство, конечно, идет в group-identifier
. Затем два умных перемещения:
NULL
в правой части (это LEFT JOIN
, помните?). Затем мы фильтруем объединенный результат, показывая только строки, где правая сторона NULL
. Итак, вы закончите:
SELECT a.*
FROM YourTable a
LEFT OUTER JOIN YourTable b
ON a.id = b.id AND a.rev < b.rev
WHERE b.id IS NULL;
Оба подхода приносят точный результат.
Если у вас есть две строки с max-value-in-group
для group-identifier
, обе строки будут в результате в обоих подходах.
Оба подхода совместимы с SQL ANSI, таким образом, будут работать с вашей любимой РСУБД, независимо от ее «вкуса».
Оба подхода также дружелюбны к производительности, однако ваш пробег может варьироваться (РСУБД, структура БД, индексы и т. д.). Поэтому, когда вы выбираете один подход над другим, benchmark . И убедитесь, что вы выбрали тот, который вам больше всего подходит.
вот еще одно решение, надеюсь, что это поможет кому-то
Select a.id , a.rev, a.content from Table1 a
inner join
(SELECT id, max(rev) rev FROM Table1 GROUP BY id) x on x.id =a.id and x.rev =a.rev
Вот хороший способ сделать это
Использовать следующий код:
with temp as (
select count(field1) as summ , field1
from table_name
group by field1 )
select * from temp where summ = (select max(summ) from temp)
Вот еще одно решение для получения записей только с полем, которое имеет максимальное значение для этого поля. Это работает для SQL400, на котором я работаю. В этом примере записи с максимальным значением в поле FIELD5 будут получены следующим оператором SQL.
SELECT A.KEYFIELD1, A.KEYFIELD2, A.FIELD3, A.FIELD4, A.FIELD5
FROM MYFILE A
WHERE RRN(A) IN
(SELECT RRN(B)
FROM MYFILE B
WHERE B.KEYFIELD1 = A.KEYFIELD1 AND B.KEYFIELD2 = A.KEYFIELD2
ORDER BY B.FIELD5 DESC
FETCH FIRST ROW ONLY)
select * from yourtable
group by id
having rev=max(rev);
ERROR: column "yourtable.content" must appear in the GROUP BY clause or be used in an aggregate function LINE 1: select * from messages
– ma11hew28
13 March 2014 в 18:17
Отсортировано поле rev в обратном порядке, а затем сгруппировано по идентификатору, который дал первую строку каждой группы, которая является самой высокой величиной rev.
SELECT * FROM (SELECT * FROM table1 ORDER BY id, rev DESC) X GROUP BY X.id;
Проверено в http: //sqlfiddle.com/ со следующими данными
CREATE TABLE table1
(`id` int, `rev` int, `content` varchar(11));
INSERT INTO table1
(`id`, `rev`, `content`)
VALUES
(1, 1, 'One-One'),
(1, 2, 'One-Two'),
(2, 1, 'Two-One'),
(2, 2, 'Two-Two'),
(3, 2, 'Three-Two'),
(3, 1, 'Three-One'),
(3, 3, 'Three-Three')
;
Это дало следующий результат в MySql 5.5 и 5.6
id rev content
1 2 One-Two
2 2 Two-Two
3 3 Three-Two
ORDER BY
в подзапросе. Поскольку многие люди будут читать ваш ответ, я пытаюсь оттолкнуть их от техники, которая сломается в их будущем. (И я не дал вам -1 голосов.)
– Rick James
3 April 2017 в 02:38
Так как это самый популярный вопрос в отношении этой проблемы, я снова опубликую здесь еще один ответ:
Похоже, что есть более простой способ сделать это (но только в MySQL):
select *
from (select * from mytable order by id, rev desc ) x
group by id
Пожалуйста, прокомментируйте ответ пользователя Bohemian в на этот вопрос за предоставление такого краткого и элегантного ответа на эту проблему.
EDIT: хотя это решение работает для многих людей, оно может быть нестабильным в долгосрочной перспективе, поскольку MySQL не гарантирует, что оператор GROUP BY вернет значимые значения для столбцов, не входящих в список GROUP BY. Поэтому используйте это решение на свой страх и риск
Я не могу ручаться за производительность, но вот трюк, вдохновленный ограничениями Microsoft Excel. У него есть некоторые хорошие функции
GOOD STUFF
ПОДХОД
Это немного уродливо и требует, чтобы вы знали что-то о диапазоне допустимых значений rev . Предположим, что мы знаем, что столбец rev - это число от 0,00 до 999, включая десятичные числа, но что только две цифры справа от десятичной точки (например, 34.17 будет действительным значением) .
Суть заключается в том, что вы создаете единый синтетический столбец путем конкатенации / упаковки первичного поля сравнения вместе с данными, которые вы хотите. Таким образом, вы можете заставить агрегированную функцию SQL MAX () возвращать все данные (поскольку она была упакована в один столбец). Затем вам нужно распаковать данные.
Вот как это выглядит с помощью приведенного выше примера, написанного на SQL
SELECT id,
CAST(SUBSTRING(max(packed_col) FROM 2 FOR 6) AS float) as max_rev,
SUBSTRING(max(packed_col) FROM 11) AS content_for_max_rev
FROM (SELECT id,
CAST(1000 + rev + .001 as CHAR) || '---' || CAST(content AS char) AS packed_col
FROM yourtable
)
GROUP BY id
Насыщение начинается с принудительного rev , чтобы быть числом известной длины символа, независимо от значения rev , так что, например,
Если вы сделаете это правильно, сравнение строк двух чисел должно дать то же самое «max», что и числовое сравнение двух чисел, и легко конвертировать обратно в исходное число, используя функцию подстроки (которая доступна в той или иной форме практически везде).
Если кто-то ищет Linq verson, это работает для меня:
public static IQueryable<BlockVersion> LatestVersionsPerBlock(this IQueryable<BlockVersion> blockVersions)
{
var max_version_per_id = blockVersions.GroupBy(v => v.BlockId)
.Select( v => new { BlockId = v.Key, MaxVersion = v.Max(x => x.Version) } );
return blockVersions.Where( v => max_version_per_id.Any(x => x.BlockId == v.BlockId && x.MaxVersion == v.Version) );
}
Это работает для меня в sqlite3:
SELECT *, MAX(rev) FROM t1 GROUP BY id
С * вы получаете дублированный столбец rev, но это не большая проблема.
SELECT * FROM Employee, где Employee.Salary in (выберите max (зарплата) из группы Employee Employee_id) ORDER BY Employee.Salary
Мне нравится использовать решение на основе NOT EXIST
для этой проблемы:
SELECT id, rev
FROM YourTable t
WHERE NOT EXISTS (
SELECT * FROM YourTable t WHERE t.id = id AND rev > t.rev
)
Третье решение, о котором я почти никогда не упоминал, имеет специфику MySQL и выглядит так:
SELECT id, MAX(rev) AS rev
, 0+SUBSTRING_INDEX(GROUP_CONCAT(numeric_content ORDER BY rev DESC), ',', 1) AS numeric_content
FROM t1
GROUP BY id
Да, это выглядит ужасно (преобразование в строку и обратно и т. д.), но по моему опыту это обычно быстрее, чем другие решения. Возможно, это только для моих случаев использования, но я использовал его на таблицах с миллионами записей и множеством уникальных идентификаторов. Возможно, это связано с тем, что MySQL очень плохо оптимизирует другие решения (по крайней мере, в 5,0 дней, когда я придумал это решение).
Важно то, что GROUP_CONCAT имеет максимальную длину для строки, которую она может построить. Вероятно, вы захотите поднять этот предел, установив переменную group_concat_max_len
. И имейте в виду, что это будет предел для масштабирования, если у вас есть большое количество строк.
В любом случае вышеупомянутое не работает напрямую, если ваше поле содержимого уже является текстом. В этом случае вы, вероятно, захотите использовать другой разделитель, например, \ 0. Вы также быстрее столкнетесь с пределом group_concat_max_len
.
Я предпочитаю использовать как можно меньше кода ...
Вы можете сделать это, используя IN
, попробуйте это:
SELECT *
FROM t1 WHERE (id,rev) IN
( SELECT id, MAX(rev)
FROM t1
GROUP BY id
)
, на мой взгляд, это меньше сложный ... легче читать и поддерживать.
НЕ mySQL, но для других людей, которые находят этот вопрос и используют SQL, другой способ разрешить проблему наибольшая-n-группа использует Cross Apply
в MS SQL
WITH DocIds AS (SELECT DISTINCT id FROM docs)
SELECT d2.id, d2.rev, d2.content
FROM DocIds d1
CROSS APPLY (
SELECT Top 1 * FROM docs d
WHERE d.id = d1.id
ORDER BY rev DESC
) d2
Что-то вроде этого?
SELECT yourtable.id, rev, content
FROM yourtable
INNER JOIN (
SELECT id, max(rev) as maxrev FROM yourtable
WHERE yourtable
GROUP BY id
) AS child ON (yourtable.id = child.id) AND (yourtable.rev = maxrev)
Я бы использовал это:
select t.*
from test as t
join
(select max(rev) as rev
from test
group by id) as o
on o.rev = t.rev
Подзапрос SELECT не слишком эффективен, но в предложении JOIN кажется полезным. Я не эксперт в оптимизации запросов, но я пробовал в MySQL, PostgreSQL, FireBird, и он работает очень хорошо.
Вы можете использовать эту схему в нескольких соединениях и с предложением WHERE. Это мой рабочий пример (решение идентично вашей задаче с таблицей «твердое»):
select *
from platnosci as p
join firmy as f
on p.id_rel_firmy = f.id_rel
join (select max(id_obj) as id_obj
from firmy
group by id_rel) as o
on o.id_obj = f.id_obj and p.od > '2014-03-01'
Его спрашивают на таблицах с подростками таких записей записей, и он занимает менее 0,01 секунды на самом деле не слишком сильная машина.
Я бы не использовал пункт IN (как упоминается выше). IN предоставляется для использования с короткими списками констант, а не как фильтр запросов, построенный на подзапросе. Это связано с тем, что подзапрос в IN выполняется для каждой отсканированной записи, которая может сделать запрос очень медленным.
and o.id = t.id
в конце (и подзапрос должен вернуть id
для этого). Не так ли?
– Dmitry Grekov
10 August 2018 в 11:37
SELECT * FROM t1 ORDER BY rev DESC LIMIT 1;
Это решение делает только один выбор из YourTable, поэтому он быстрее. Он работает только для MySQL и SQLite (для SQLite удаляет DESC) в соответствии с тестом на sqlfiddle.com. Возможно, он может быть настроен для работы на других языках, с которыми я не знаком.
SELECT *
FROM ( SELECT *
FROM ( SELECT 1 as id, 1 as rev, 'content1' as content
UNION
SELECT 2, 1, 'content2'
UNION
SELECT 1, 2, 'content3'
UNION
SELECT 1, 3, 'content4'
) as YourTable
ORDER BY id, rev DESC
) as YourTable
GROUP BY id
ERROR: column "your table.reb" must appear in the GROUP BY clause or be used in an aggregate function LINE 1: SELECT *
– ma11hew28
13 March 2014 в 18:26
Ни один из этих ответов не работал для меня.
Это то, что сработало для меня.
with score as (select max(score_up) from history)
select history.* from score, history where history.score_up = score.max
Я использовал ниже, чтобы решить свою проблему. Сначала я создал временную таблицу и вставил максимальное значение rev на уникальный идентификатор.
CREATE TABLE #temp1
(
id varchar(20)
, rev int
)
INSERT INTO #temp1
SELECT a.id, MAX(a.rev) as rev
FROM
(
SELECT id, content, SUM(rev) as rev
FROM YourTable
GROUP BY id, content
) as a
GROUP BY a.id
ORDER BY a.id
Затем я присоединил эти максимальные значения (# temp1) ко всем возможным комбинациям id / content. Делая это, я, естественно, отфильтровываю не максимальные комбинации id / content, и оставляю их только с максимальными значениями rev для каждого.
SELECT a.id, a.rev, content
FROM #temp1 as a
LEFT JOIN
(
SELECT id, content, SUM(rev) as rev
FROM YourTable
GROUP BY id, content
) as b on a.id = b.id and a.rev = b.rev
GROUP BY a.id, a.rev, b.content
ORDER BY a.id
Многие, если не все, другие ответы здесь подходят для небольших наборов данных. Для масштабирования требуется больше внимания. См. здесь .
В нем обсуждается несколько более быстрых способов делать групповые макс и верхние N на группу.
Другой способ выполнения задания - использовать аналитическую функцию MAX () в предложении OVER PARTITION
SELECT t.*
FROM
(
SELECT id
,rev
,contents
,MAX(rev) OVER (PARTITION BY id) as max_rev
FROM YourTable
) t
WHERE t.rev = t.max_rev
. Другое решение OVER PARTITION, уже зарегистрированное в этом сообщении, -
SELECT t.*
FROM
(
SELECT id
,rev
,contents
,ROW_NUMBER() OVER (PARTITION BY id ORDER BY rev DESC) rank
FROM YourTable
) t
WHERE t.rank = 1
Этот 2 SELECT хорошо работает на Oracle 10g.
Если у вас много полей в инструкции select, и вы хотите получить последнее значение для всех этих полей с помощью оптимизированного кода:
select * from
(select * from table_name
order by id,rev desc) temp
group by id
Я разочарован тем, что в ответе не было предложено решение функции SQL-окна:
SELECT a.id, a.rev, a.contents
FROM (SELECT id, rev, contents,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY rev DESC) rank
FROM YourTable) a
WHERE a.rank = 1
Добавлено в SQL-стандарте ANSI / ISO Standard SQL: 2003 и более поздних версиях с ANSI / ISO Standard SQL: 2008, window ( или окна) доступны со всеми основными поставщиками сейчас. Существует множество типов ранговых функций, доступных для решения проблемы связи: RANK, DENSE_RANK, PERSENT_RANK
.
Мне нравится делать это, оценивая записи по некоторым столбцам. В этом случае значения ранга rev
группируются по id
. Те, у кого выше rev
, будут иметь более низкий рейтинг. Таким образом, наивысший rev
будет иметь ранжирование 1.
select id, rev, content
from
(select
@rowNum := if(@prevValue = id, @rowNum+1, 1) as row_num,
id, rev, content,
@prevValue := id
from
(select id, rev, content from YOURTABLE order by id asc, rev desc) TEMP,
(select @rowNum := 1 from DUAL) X,
(select @prevValue := -1 from DUAL) Y) TEMP
where row_num = 1;
Не уверен, что введение переменных делает все это медленнее. Но, по крайней мере, я не дважды запрашиваю YOURTABLE
.
Еще одно решение заключается в использовании коррелированного подзапроса:
select yt.id, yt.rev, yt.contents
from YourTable yt
where rev =
(select max(rev) from YourTable st where yt.id=st.id)
Наличие индекса (id, rev) делает подзапрос почти как простой поиск ...
Ниже приведены сравнения с решениями в ответе @ AdrianCarneiro (подзапрос, leftjoin), основанные на измерениях MySQL с таблицей InnoDB размером ~ 1 миллион записей, размер группы: 1-3.
Хотя для полной проверки таблицы подзапрос / leftjoin / коррелированные тайминги относятся друг к другу как 6/8/9, когда дело доходит до прямого поиска или партии (id in (1,2,3)
), подзапрос намного медленнее, чем другие (из-за повторного ввода подзапроса). Тем не менее я не мог отличить левый и коррелированный решения от скорости.
Наконец, поскольку leftjoin создает n * (n + 1) / 2, объединяется в группы, на его производительность может сильно влиять размер групп ...
Я думаю, что это самое простое решение:
SELECT *
FROM
(SELECT *
FROM Employee
ORDER BY Salary DESC)
AS employeesub
GROUP BY employeesub.Salary;
Если вам нужна только одна строка, это еще проще:
SELECT *
FROM Employee
ORDER BY Employee.Salary DESC
LIMIT 1
Я также считаю, что проще всего сломать, понять и изменить другие цели:
Понимание этого подхода, решение любой из этих подобных проблем становится тривиальным: получить сотрудника с наименьшей зарплатой (сменить DESC на ASC), получить топ-десять сотрудников (изменить LIMIT 1 до LIMIT 10), сортировать по средства другого поля (изменение ЗАКАЗА ПО РАБОТЕ. Сотрудник по заказу Employee.Commission) и т. д.
Как насчет этого:
select all_fields.*
from (select id, MAX(rev) from yourtable group by id) as max_recs
left outer join yourtable as all_fields
on max_recs.id = all_fields.id
select id, max(rev), rev from YourTable group by id
, и вы понимаете, что я имею в виду. Не торопитесь и постарайтесь это понять – Adrian Carneiro 12 October 2011 в 21:05group_identifier
, который может быть одним или несколькими столбцами. В вашем случаеgroup_identifier
представляет собой комбинацию имени и возраста – Adrian Carneiro 12 December 2012 в 18:50DISTINCT ON (yt.id)
после начальногоSELECT
. Это сделало мой запрос занявшим в два раза длиннее. Итак, я не связываюсь, потому что в моем случае связи практически невозможны. – ma11hew28 14 March 2014 в 02:29max
не будет выполняться для каждой группы, состоящей из одной строки, а не всех строк в целом. – Gherman 18 September 2014 в 09:24