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!
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
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
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"
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
Related
I am currently creating a LibreOffice Base application to determine the winners of a competition. The winner is determined by the number of seconds he takes from start to finish. How do I get a placement field, which is not part of the actual table?
SELECT "Team_ID", "Team_Shortname", "TotalTimeInSeconds", (HERE) AS "Placement" FROM "Team"
I found out how to do it on a seperate query, but I don't know how to combine it, how would I get the ID in the query again?
"select count(*) from Team where TotalTimeInSeconds < (select TotalTimeInSeconds
from Team where Team_ID = " + teamId + ");"
Makes sense now.
SELECT "t"."Team_ID", "t"."Team_Shortname", "t"."TotalTimeInSeconds",
( SELECT COUNT(*) FROM "Team" WHERE "TotalTimeInSeconds" < "t"."TotalTimeInSeconds" )
AS "Placement" FROM "Team" "t"
SELECT
RANK() OVER (ORDER BY "TotalTimeInSeconds" ASC) AS placement,
"Team_ID", "Team_Shortname", "TotalTimeInSeconds"
FROM "Team" ORDER BY "TotalTimeInSeconds" ASC;
For more reading : Rank, Dense Rank , Row Num
I have the following query:
SELECT "IMPORTACIONCOLUMN3", "role", COUNT("IMPORTACIONCOLUMN1")
FROM MYTABLE
WHERE ID = 9
GROUP BY "IMPORTACIONCOLUMN3", "role"
This gives me the following result:
I would like to achieve the following:
The "unique" values are grouped together (i.e. Instead of having 4 values of "Robot 1" these are grouped togehter in just 1 cell summing the count values.
The second group by or subquery has to be the same count, but with role instead of "IMPORTACIONCOLUM3"
Is it possible (for the second picture) to "link" the values either by index or adding an extra column to reference them (i.e. There's two "Solicitante" with a count value of "52" but it refers to "Robot 1" and other to "Solicitante" with count value of "58" links to "Robot 2"
The second image represent visually what I'm trying to explain.
I have been trying on my own but only have reached the following:
select "IMPORTACIONCOLUMN3", count("IMPORTACIONCOLUMN1")
from
(
select "IMPORTACIONCOLUMN1", count("role"), "IMPORTACIONCOLUMN3"
from MYTABLE
WHERE ID = 9
group by "IMPORTACIONCOLUMN1", "IMPORTACIONCOLUMN3"
) as tmp
group by "IMPORTACIONCOLUMN3"
But it is not yet the result I am looking for.
Thanks in advance for your help and tips!
EDIT:
Explaining my desired output in detail
Each one of "Robot 1, 2, 3" have roles such as "Solicitante", "Gerente", etc. with different values.
i.e. The first row "Humano" value "243" is the sum of "Agente de Compras - 95", "Gerente Financiero - 37", "Gerente Solicitante - 45", "Proovedor - 31", "Solicitante - 60".
I am linking these by the column "GRAFICOCOLUMNARECURSIVOID" with contains the index of whatever "Robot" these "roles" are from.
I would like to achieve a query containing subquerys that allows me to have this output.
Try this for question number 1:
SELECT "IMPORTACIONCOLUMN3", COUNT("IMPORTACIONCOLUMN1")
FROM MYTABLE
WHERE ID = 9
GROUP BY "IMPORTACIONCOLUMN3"
the problem is Role: Robot 1 have 4 roles
and this for question 2:
SELECT "role", COUNT("IMPORTACIONCOLUMN1")
FROM MYTABLE
WHERE ID = 9
GROUP BY "role"
Question 3, I don't understand what you are asking for. Please make an example.
I need to match a user input against a string column. Both contain space-separated words.
The ordering criteria is:
count of words matched from the beginning (prefix match) desc
count of words matched desc
columns where matched words come in the same order as in the input phrase come first
So given the following sample data
"one sample"
"un moment"
"no match"
"sample uno"
"uno sample"
"sample oun"
and the sample input "sa un foo", the output should be:
"sample uno" - 2 prefix matches
"uno sample" - the same but the order of words differs
"sample oun" - 1 prefix match + 2 words matched
"un moment", "one sample" - 1 prefix match
The question is: can I implement this in a single SQL query (postgresql)?
I'm fairly unexperienced with SQL, so I appreciate any help. Thanks!
I include a simple SQL FIDDLE
first asign and id to each row
split each data by space
split input by space
cross join both tables and check if input appear on data.
last join back to original table and count how many prefix and contain have.
There is a case I think may require special atention if one input words appear as prefix and second word appear as contain of same word
data: FORMAT
input: FO AT
SQL FIDDLE DEMO
WITH data as (
SELECT
row_number() OVER (ORDER BY field) AS id,
field
FROM
dtable
),
data_split as (
SELECT
id,
unnest(string_to_array(field, ' ')) AS elem
FROM data
),
input_split as (
SELECT
unnest(string_to_array(field, ' ')) AS elem
FROM input
),
match as (
SELECT *, strpos(d.elem, i.elem) as match_pos
FROM input_split i, data_split d
)
select
match.id,
data.field,
SUM( CASE WHEN match_pos = 1 THEN 1 ELSE 0 END ) prefix,
SUM( CASE WHEN match_pos > 1 THEN 1 ELSE 0 END ) contain
from
match inner join
data on match.id = data.id
group by match.id, data.field
order by 3 desc, 4 desc
I have a table with 3 columns: "Dept Number" and "Class Number" and "Description". If the user enter values 21-1 and 24-12 where the left term represents the department number and right term represents the class number, I want to search the table for those items based on its dept number and class number (Here, dept# = 21 and class# = 1) and displays its description. How can I write the SQL query for that?
Note: the user can enter more than 1 value. So, I am thinking about making 2 lists: 1 for dept# and other for class#. But, I am not sure how to search the database using these lists
Here is a code example for SQL Server and Oracle.
SQL Server:
SELECT *
FROM yourTable
WHERE dept = CAST(SUBSTRING(N'21-1',1,CHARINDEX(N'-',N'21-1')-1) as int)
AND class = CAST(SUBSTRING(N'21-1',CHARINDEX(N'-',N'21-1')+1, LEN(N'21-1')) as int)
Oracle
SELECT *
FROM yourTable
WHERE dept = CAST(SUBSTR(N'21-1',1,CHARINDEX(N'-',N'21-1')-1) as int)
AND class = CAST(SUBSTR(N'21-1',CHARINDEX(N'-',N'21-1')+1, LENGTH(N'21-1')) as int)
Please tag your question correctly. I hope this helps you.
Sorry for being a noob, but I believe this is the right place for the help I need.
I just started working on SSRS reports (2005) and I would like to find out how I can add a filter dropdown with multiple options that execute a sort. I have imported a list into my table and have the apropriate fields needed for this sort.
IE. I would like to have a dropdown box named "Sort By" with the available selections:
CustomerName
ZipCode, SIC
SIC, City
Each one of those performs the specific order by function that is selected when viewing the report.
I played around and was able to set datasets and add filters, but that isn't optimal because (for instance) you would have to know the exact ZipCode and SIC match to return any results.
There has to be an easy way to return this select statement with multiple order by criteria based on the selection of the dropdown list, but I can't find it if there is.
Any assistance would be greatly appreciated!
I can think of a couple of options. In both cases I've assumed a parameter SortOrder which contains the following values:
CustomerName
ZipCode, SIC
SIC, City
Apply sort expressions to Table based on Parameter
I've applied to sorting expressions to the Table:
First sort:
=Switch(Parameters!SortOrder.Value = "CustomerName", Fields!CustomerName.Value
, Parameters!SortOrder.Value = "ZipCode, SIC", Fields!ZIP.Value
, Parameters!SortOrder.Value = "SIC, City", Fields!SIC.Value)
Second sort:
=Switch(Parameters!SortOrder.Value = "CustomerName", Fields!CustomerName.Value
, Parameters!SortOrder.Value = "ZipCode, SIC", Fields!SIC.Value
, Parameters!SortOrder.Value = "SIC, City", Fields!City.Value)
Apply sort in query
You can add an order by to your Dataset query based on the parameter to perform the same operation:
...
order by case #SortOrder when 'CustomerName' then CustomerName
when 'ZipCode, SIC' then ZIP
when 'SIC, City' then SIC
end
, case #SortOrder when 'CustomerName' then CustomerName
when 'ZipCode, SIC' then SIC
when 'SIC, City' then City
end
In both cases you get a parameter-based sort: