Reputation: 33
I have a weird table-sorting issue that I cannot figure out in Excel or SQL.
Here's a table sorted by column 2, "Letter".
Name | Letter |
---|---|
Dan | A |
Moe | A |
Ted | B |
Dan | C |
Joe | F |
Noe | F |
What I need is the table sorted by Letter BUT... if there are any duplicates in the "Name" column, I need those grouped--which would break the sorting in column 2. So below, even though the table is sorted by Letter, I want the two Dans together:
Name | Letter |
---|---|
Dan | A |
Dan | C |
Moe | A |
Ted | B |
Joe | F |
Noe | F |
Thanks for any help!
Upvotes: 0
Views: 95
Reputation: 1269773
I think you just want two keys in your order by
clause:
order by name, letter
EDIT:
If you want to sort by name
based on the lowest letter, then you would use window functions:
order by min(letter) over (partition by name),
name, letter
Upvotes: 0
Reputation: 60224
This Power Query solution (available in Windows Excel 2010+ and Office 365) seems to do what you want on your database.
Please read the comments.
I group by Name and then sort by letter (as well as sort each subGroup by letter).
M Code
let
Source = Excel.CurrentWorkbook(){[Name="Table7"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Name", type text}, {"Letter", type text}}),
//Group by name
//Sort each subgroup and extract the initial letter
//Generate a Table with each subtable properly sorted
#"Grouped Rows" = Table.Group(#"Changed Type", {"Name"}, {
{"All", each _, type table [Name=nullable text, Letter=nullable text]},
{"SortSubGroup", each Table.Sort(_,"Letter")},
{"letter1", each List.Sort([Letter]){0}, type text}
}),
//Sort by initial letter and then by Name
//Remove the unneeded columns and expand the subTables
#"Sorted Rows" = Table.Sort(#"Grouped Rows",{{"letter1", Order.Ascending}, {"Name", Order.Ascending}}),
#"Removed Columns" = Table.RemoveColumns(#"Sorted Rows",{"Name", "All", "letter1"}),
#"Expanded SortSubGroup" = Table.ExpandTableColumn(#"Removed Columns", "SortSubGroup", {"Name", "Letter"}, {"Name", "Letter"})
in
#"Expanded SortSubGroup"
Upvotes: 1
Reputation: 74605
You didn't really say where in the results you wanted the Dans but let's use a window function to count the number of same names and sort by that initially (descending, meaning the dans will sort nearer the top)
SELECT *
FROM t
ORDER BY COUNT(*) OVER(PARTITION BY name) DESC, letter
If you have eg two Fred and you want them to sort together and not mix up with the dans, consider
SELECT *
FROM t
ORDER BY CASE WHEN COUNT(*) OVER(PARTITION BY name) = 1 THEN NULL ELSE name END DESC, letter
This effectively puts unique names "in one basket" that is then sorted by letter and for "non unique names" they clump together by the name and then sort by the letter
Upvotes: 1
Reputation: 48121
I would try something like this.
SELECT t.name, t.letter
FROM table t
JOIN (SELECT table.name, MIN(table.letter) AS min_letter_by_name
FROM table GROUP BY table.name)
ON t.name = table.name
ORDER BY min_letter_by_name, name, letter
Upvotes: 2