diff --git a/DevTips/.vscode/launch.json b/DevTips/.vscode/launch.json
new file mode 100644
index 0000000..cd6b118
--- /dev/null
+++ b/DevTips/.vscode/launch.json
@@ -0,0 +1,24 @@
+{
+ // IntelliSense를 사용하여 가능한 특성에 대해 알아보세요.
+ // 기존 특성에 대한 설명을 보려면 가리킵니다.
+ // 자세한 내용을 보려면 https://go.microsoft.com/fwlink/?linkid=830387을(를) 방문하세요.
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": ".NET Core Launch (console)",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": "build",
+ "program": "${workspaceFolder}/DevTips/bin/Debug/net7.0/DevTips.dll",
+ "args": [],
+ "cwd": "${workspaceFolder}/DevTips",
+ "console": "internalConsole",
+ "stopAtEntry": false
+ },
+ {
+ "name": ".NET Core Attach",
+ "type": "coreclr",
+ "request": "attach"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/DevTips/.vscode/tasks.json b/DevTips/.vscode/tasks.json
new file mode 100644
index 0000000..eca9e25
--- /dev/null
+++ b/DevTips/.vscode/tasks.json
@@ -0,0 +1,41 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/DevTips/DevTips.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "publish",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "publish",
+ "${workspaceFolder}/DevTips/DevTips.csproj",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "watch",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "watch",
+ "run",
+ "--project",
+ "${workspaceFolder}/DevTips/DevTips.csproj"
+ ],
+ "problemMatcher": "$msCompile"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/DevTips/DevTips.sln b/DevTips/DevTips.sln
new file mode 100644
index 0000000..4adf4bb
--- /dev/null
+++ b/DevTips/DevTips.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevTips", "DevTips\DevTips.csproj", "{E0D7D3A3-0C0F-4499-BD11-13336302EB8D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E0D7D3A3-0C0F-4499-BD11-13336302EB8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E0D7D3A3-0C0F-4499-BD11-13336302EB8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E0D7D3A3-0C0F-4499-BD11-13336302EB8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E0D7D3A3-0C0F-4499-BD11-13336302EB8D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/DevTips/DevTips/DevTips.csproj b/DevTips/DevTips/DevTips.csproj
new file mode 100644
index 0000000..f02677b
--- /dev/null
+++ b/DevTips/DevTips/DevTips.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Exe
+ net7.0
+ enable
+ enable
+
+
+
diff --git a/DevTips/DevTips/Program.cs b/DevTips/DevTips/Program.cs
new file mode 100644
index 0000000..4595389
--- /dev/null
+++ b/DevTips/DevTips/Program.cs
@@ -0,0 +1,14 @@
+using DevTips.Tips;
+
+namespace DevTips;
+class Program
+{
+ static void Main(string[] args)
+ {
+ LinqGroupMinMax.Print();
+ System.Console.WriteLine();
+ LinqGroupMinMax.Client1();
+ System.Console.WriteLine();
+ LinqGroupMinMax.Client2();
+ }
+}
diff --git a/DevTips/DevTips/Tips/LinqGroupMinMax.cs b/DevTips/DevTips/Tips/LinqGroupMinMax.cs
new file mode 100644
index 0000000..013bab2
--- /dev/null
+++ b/DevTips/DevTips/Tips/LinqGroupMinMax.cs
@@ -0,0 +1,101 @@
+using System.Data;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace DevTips.Tips
+{
+ class LinqGroupMinMax
+ {
+ public static void Print()
+ {
+ DataTable table = GetData();
+ foreach (DataRow row in table.Rows)
+ {
+ System.Console.WriteLine($"\t{row["GroupID"]}\t{row["SalesPerson"]}\t{row["Sales"]}");
+ }
+ }
+
+ public static void Client1()
+ {
+ var data = GetData().AsEnumerable();
+
+ var result = from row in data
+ group row by row.Field("GroupID") into g
+ select new
+ {
+ GroupID = g.Key,
+ SalesPerson = g.First(g2 => g2.Field("Sales") == g.Min(g3 => g3.Field("Sales"))).Field("SalesPerson"),
+ Sales = g.Min(p => p.Field("Sales"))
+ };
+
+ foreach (var r in result)
+ {
+ System.Console.WriteLine($"{r.GroupID},{r.SalesPerson} , {r.Sales}");
+ }
+ }
+
+ public static void Client2()
+ {
+ var data = GetData().AsEnumerable();
+
+ var result = data.GroupBy(t => t.Field("GroupID")).Select(g => new
+ {
+ GroupID = g.Key,
+ SalesPerson = g.First(g2 => g2.Field("Sales") == g.Min(g3 => g3.Field("Sales"))).Field("SalesPerson"),
+ Sales = g.Min(p => p.Field("Sales"))
+ });
+ }
+
+ private static DataTable GetData()
+ {
+ DataTable table = new DataTable();
+ table.Columns.Add("GroupID", typeof(int));
+ table.Columns.Add("SalesPerson", typeof(string));
+ table.Columns.Add("Sales", typeof(int));
+
+ DataRow row = table.NewRow();
+ row["GroupID"] = 1;
+ row["SalesPerson"] = "Lee";
+ row["Sales"] = 900;
+ table.Rows.Add(row);
+
+ row = table.NewRow();
+ row["GroupID"] = 1;
+ row["SalesPerson"] = "Li";
+ row["Sales"] = 800;
+ table.Rows.Add(row);
+
+ row = table.NewRow();
+ row["GroupID"] = 1;
+ row["SalesPerson"] = "Park";
+ row["Sales"] = 990;
+ table.Rows.Add(row);
+
+ row = table.NewRow();
+ row["GroupID"] = 2;
+ row["SalesPerson"] = "Tom";
+ row["Sales"] = 500;
+ table.Rows.Add(row);
+
+ row = table.NewRow();
+ row["GroupID"] = 2;
+ row["SalesPerson"] = "Jane";
+ row["Sales"] = 400;
+ table.Rows.Add(row);
+
+ row = table.NewRow();
+ row["GroupID"] = 3;
+ row["SalesPerson"] = "Irina";
+ row["Sales"] = 600;
+ table.Rows.Add(row);
+
+ row = table.NewRow();
+ row["GroupID"] = 3;
+ row["SalesPerson"] = "Yong";
+ row["Sales"] = 633;
+ table.Rows.Add(row);
+
+ return table;
+ }
+ }
+}
\ No newline at end of file