C#では次のようになります。
table
.GroupBy(row => row.SomeColumn)
.Select(group => group
.OrderBy(row => row.AnotherColumn)
.First()
)
Linq-To-Sqlはそれを次のT-SQLコードに変換します。
SELECT [t3].[AnotherColumn], [t3].[SomeColumn]
FROM (
SELECT [t0].[SomeColumn]
FROM [Table] AS [t0]
GROUP BY [t0].[SomeColumn]
) AS [t1]
OUTER APPLY (
SELECT TOP (1) [t2].[AnotherColumn], [t2].[SomeColumn]
FROM [Table] AS [t2]
WHERE (([t1].[SomeColumn] IS NULL) AND ([t2].[SomeColumn] IS NULL))
OR (([t1].[SomeColumn] IS NOT NULL) AND ([t2].[SomeColumn] IS NOT NULL)
AND ([t1].[SomeColumn] = [t2].[SomeColumn]))
ORDER BY [t2].[AnotherColumn]
) AS [t3]
ORDER BY [t3].[AnotherColumn]
ただし、MySQLとは互換性がありません。
書くとき
SELECT AnotherColumn
FROM Table
GROUP BY SomeColumn
;
できます。グループ化キーに属さない列は、なんらかの集計なしで参照されているため、他のRDBMSのこのようなステートメントのIIRCは不可能です。
この「癖」は、私が望むものに非常に近い振る舞いをします。だから私はそれを使って、私が望んでいた結果を得ました:
SELECT * FROM
(
SELECT * FROM `table`
ORDER BY AnotherColumn
) t1
GROUP BY SomeColumn
;
C#がわからず、指定されたクエリを理解できなかったため、回答は投稿のタイトルのみに基づいていました。しかし、MySQLでは、サブセレクトを試すことをお勧めします。最初に興味深い列の主キーのセットを取得してから、それらの行からデータを選択します。
SELECT somecolumn, anothercolumn
FROM sometable
WHERE id IN (
SELECT min(id)
FROM sometable
GROUP BY somecolumn
);
もう1つ試すことができますが、そのIDフィールドは必要ありません。
select some_column, min(another_column)
from i_have_a_table
group by some_column
それでも、主キーを追加する必要があるというlfagundesに同意します。
また、これを行うと、他の値が結果のsome_colum、another_columnのペアと同じ行になることは(簡単に)できないことに注意してください!そのためにはlfagundesのアプローチとPKが必要です!
何らかの集計関数を使用して、必要なAnotherColumnの値を取得する必要があります。つまり、SomeColumnの各値に対してAnotherColumnの最小値が必要な場合(数値または辞書順)、次を使用できます。
SELECT SomeColumn, MIN(AnotherColumn)
FROM YourTable
GROUP BY SomeColumn
うまくいけば役立つリンク:
http://dev.mysql.com/doc/refman/5.1/en/group-by-functions.html
http://www.oreillynet.com/databases/blog/2007/05/debunking_group_by_myths.html
MySQL 5.7.5以降では、機能依存の検出が実装されています。 ONLY_FULL_GROUP_BY SQLモードが有効になっている場合(デフォルト)、MySQLは、選択リスト、HAVING条件、またはORDER BYリストが、GROUP BY句で名前が指定されておらず、機能的に依存していない非集計列を参照するクエリを拒否します。
これは、@ Jader Diasのソリューションがどこでも機能しないことを意味します。
ONLY_FULL_GROUP_BY
有効になっています:
SET @row := NULL;
SELECT
SomeColumn,
AnotherColumn
FROM (
SELECT
CASE @id <=> SomeColumn AND @row IS NOT NULL
WHEN TRUE THEN @row := @row+1
ELSE @row := 0
END AS rownum,
@id := SomeColumn AS SomeColumn,
AnotherColumn
FROM
SomeTable
ORDER BY
SomeColumn, -AnotherColumn DESC
) _values
WHERE rownum = 0
ORDER BY SomeColumn;
私は答えの中に次の解決策を見たことがないので、それをそこに置くと思った。
問題は、AnotherColumn
でグループ化されたすべてのグループで、SomeColumn
で順序付けられたときに最初の行である行を選択することです。
次のソリューションは、MySQLでこれを行います。 id
は、_-
_(セパレータとして使用する)を含む値を保持してはならない一意の列でなければなりません。
_select t1.*
from mytable t1
inner join (
select SUBSTRING_INDEX(
GROUP_CONCAT(t3.id ORDER BY t3.AnotherColumn DESC SEPARATOR '-'),
'-',
1
) as id
from mytable t3
group by t3.SomeColumn
) t2 on t2.id = t1.id
-- Where
SUBSTRING_INDEX(GROUP_CONCAT(id order by AnotherColumn desc separator '-'), '-', 1)
-- can be seen as:
FIRST(id order by AnotherColumn desc)
-- For completeness sake:
SUBSTRING_INDEX(GROUP_CONCAT(id order by AnotherColumn desc separator '-'), '-', -1)
-- would then be seen as:
LAST(id order by AnotherColumn desc)
_
MySQLバグトラッカーにはFIRST()
およびLAST()
に 機能要求 がありますが、何年も前に閉じられました。
さらに別の方法(主キーなし)では、JSON関数を使用します。
select somecolumn, json_unquote( json_extract(json_arrayagg(othercolumn), "$[0]") )
from sometable group by somecolumn
または5.7.22以前
select somecolumn,
json_unquote(
json_extract(
concat('["', group_concat(othercolumn separator '","') ,'"]')
,"$[0]" )
)
from sometable group by somecolumn
グループ化する前に順序付け(またはフィルタリング)を実行できます。
select somecolumn, json_unquote( json_extract(json_arrayagg(othercolumn), "$[0]") )
from (select * from sometable order by othercolumn) as t group by somecolumn
...またはグループ化後(もちろん):
select somecolumn, json_unquote( json_extract(json_arrayagg(othercolumn), "$[0]") ) as other
from sometable group by somecolumn order by other
確かに、かなり複雑であり、パフォーマンスはおそらく大きくありません(大きなデータでテストしなかったため、私の限られたデータセットでうまく機能します)。
SELECT
t1.*
FROM
table_name AS t1
LEFT JOIN table_name AS t2 ON (
t2.group_by_column = t1.group_by_column
-- group_by_column is the column you would use in the GROUP BY statement
AND
t2.order_by_column < t1.order_by_column
-- order_by_column is column you would use in the ORDER BY statement
-- usually is the autoincremented key column
)
WHERE
t2.group_by_column IS NULL;
MySQL v8 +では、ウィンドウ関数を使用できます
さらに別の方法
ビューで機能するグループから最大を選択します
SELECT * FROM action a
WHERE NOT EXISTS (
SELECT 1 FROM action a2
WHERE a2.user_id = a.user_id
AND a2.action_date > a.action_date
AND a2.action_type = a.action_type
)
AND a.action_type = "CF"
これはどう:
SELECT SUBSTRING_INDEX(
MIN(CONCAT(OrderColumn, '|', IFNULL(TargetColumn, ''))
), '|', -1) as TargetColumn
FROM table
GROUP BY GroupColumn