ORDER BY FIELD() and duplicate data - mysql

Lets say I have the following query.
SELECT stringdata FROM table ORDER BY FIELDS( stringdata, 'tg','nk','mg','pl') asc;
For some reason I'm getting the results at the very bottom. How can I get the query to put the results starting from 'tg' at row 1 rather than the last row in the results?
Not only that but there's more than one 'tg' in the data, I'd like it to sort it in this expected output:
stringdata
__________
'tg'
'tg'
'tg'
'nk'
'nk'
'mg'
'mg'
'mg'
'pl'
So far using ORDER BY Fields() is only sorting one instance of the data rather than all.
Using desc instead of asc in the query works as expected. I get 'pl' on the first row, then 'mg', 'nk', etc.

Normally the FIELD clause in ORDER BY works something like
SELECT * FROM table ORDER BY FIELD(field, high_priority, second_high,
,....., low_priority);
So in your query, the sorting took place as you mentioned and when you gave the ASC it printed from the lowest_priority. So, for your case, if you want tg at the top, you can either reorder the priority in the FIELDS or as you have already tried use desc

If you want first rows with 'tg', then rows with .... then with 'pl' and then all the rest sorted (ASC or DESC) use this:
SELECT stringdata
FROM table
ORDER BY FIELD( stringdata, 'pl','mg', 'nk', 'tg') DESC
, stringdata ASC --- or DESC

Related

Obtaining the maximum value with Order By and Limit 1

First of all, I am using MySQL. When I make the following query:
SELECT CodE,sum(tiempo) AS 'tiempo total'
FROM Participa
GROUP BY CodE
ORDER BY 'tiempo total' DESC LIMIT 1;
it shows me the first line of my table instead of the MAX value. However, If I make the following query:
SELECT CodE,sum(tiempo)
FROM Participa
GROUP BY CodE
ORDER BY 2 DESC LIMIT 1
I get the correct result.
I have just changed the alias 'tiempo total' for somthing that should be equivalent.
How it´s possible?
Only use single quotes for string and date constants -- never for column aliases. So:
SELECT CodE, sum(tiempo) AS `tiempo total`
FROM Participa
GROUP BY CodE
ORDER BY `tiempo total` DESC
LIMIT 1;
You are ordering by a constant string, not the name of a column. Hence, if you get the maximum in your query, it would be a total accident.
Note: You can get around these issues by giving columns names that never need to be escaped:
SELECT CodE, sum(tiempo) AS tiempo_total
FROM Participa
GROUP BY CodE
ORDER BY tiempo_total DESC
LIMIT 1;
Easier to type, too.

Group different groups as the same and count?

I have the following query:
SELECT owner,
typeOwner,
type,
count(*) AS count
FROM myTable
GROUP BY typeOwner
ORDER BY count DESC
LIMIT 0, 30
Now , the typeOwner values = '<test>a</test>' but , some times the typeOwner field will have some string else like '<test>b</test>, how can i let this query count the <test>b</test> as a group of '<test>a</test>.
I want to make an exception for this, I mean typeOwner <test>a</test> AND typeOwner <test>b</test> should be counted as one row that have two count.
here's a fiddle : http://sqlfiddle.com/#!2/70053/1 , take look
actually these are should be grouped by <type></type><aId></aId>
"actually these are should be grouped by "
You can GROUP BY something relatively ugly like:
GROUP BY LEFT(typeOwner, position('<xType>' in typeOwner) -1)
But you are probably better off preprocessing the data in some fashion. I'm not sure how MySQL handles xml, but in SQL server I might extract the XML values into first class relation fields if I needed to do this sort of processing with any frequency.
sqlfiddle.com
Based on your sqlfiddle, this works
SELECT
left(typeOwner, instr(typeOwner, '<xType>')-1) as typeOwner,
owner,type, count(*) as count
FROM `test`
GROUP BY left(typeOwner, instr(typeOwner, '<xType>')-1)
ORDER BY count DESC
LIMIT 0 , 30

MySQL UNION SELECT statement order by two different columns

I have a table with a column called "myorder". I want to only order the first 5 elements in ascending order by using the column "myorder" and then the rest of the elements ordererd by id in descending order. I've tried but I don't seem to get this 100%. I have created a sqlfiddle with this simple example. Can anybody help me?
The order in the sqlfiddle should be: Blue, Brown, Yellow, Red, Green, Orange, Gray, Black, White.
maybe try
SELECT * from tbl ORDER BY IF(myorder=0, 2147483647, myorder) ASC, id DESC
if by "first 5" you mean ones with nonzero myorder
Append this to the end of your sql statement:
ORDER BY FIELD(id, 3,4,5,1,2,9,8,7,6)
This will manually sort the results based on the id field in the specified order getting the colours in order.
Alternatively you could:
ORDER BY FIELD(NAME, BLUE,BROWN,YELLOW......)
Union does not preserves order, at least not in all databases.
To get this done you need to select a fake column and use order on the results (total)
Here is a solution:
(
SELECT Id, myorder, myorder as fake, name from tbl WHERE myorder!=0) UNION
(SELECT id, myorder, 2000 as fake,name from tbl WHERE myorder=0) ORDER BY fake asc, id desc
This Will work in any case, as long as you keep the fake number high enough.
Can we have NULL value instead of zero when myorder is not specified?
If so we can do this:
SELECT * from tbl ORDER BY -myorder DESC, id DESC
Fiddle:
http://sqlfiddle.com/#!2/ef9ee/4
Hint on forcing nulls to sort last: MySQL Orderby a number, Nulls last
Use a CASE statement and the following trick (for example):
SELECT *,
CASE myorder
WHEN 0 THEN id
ELSE 99999999 - myorder
END AS ord
FROM tbl
ORDER BY ord DESC
SQL Fiddle

SQL select with custom ORDER BY data

I have data TSA, TSB, TSC, Total.
How to display this alphabetically with Total always the last one.
Currently I have this and of course it doesn't work.
select * from table where main_id =x group by col-name asc
Certainly I can't use desc because I have another record ABC, BCA, CDA, Total.
So how to add "except if col-name is Total"? or perhaps there is another way?
Kind of hard to be sure with your post (not a lot of detail in there). But you could probably use a case statement to evaluate your column, and sort on that. Something like
case when <your column> = 'Total' then 'ZZZ' else <your column> end as SortKey
Then you can just order by that new column.
User order by field:
select * from table
where main_id =x
order by FIELD( `col-name`, 'Total' ), t;
See:
SQL Fiddle Example
Refer to:
MySQL: FIELD(str,str1,str2,str3,...)
Return the index (position) of the first argument in the subsequent
arguments.

Method to sort MYSQL results by an arbitriary letter (ie, show all rows starting with F first)

I have a column of states, and, depending on the query, I want to order by results by a particular state, then by id (Asc or Desc, depending). For instance, I might want to show all rows with state "HI", sorted by ID desc, and then all the other rows, sorted by id desc.
I was hoping I could do this in one query, rather than getting all my favored state results, and then getting the rest. Can I?
How about:
SELECT id, state
FROM sometable
ORDER BY IF(state = 'HI', 0, 1) ASC, id DESC;
This will sort 'HI' rows first. If you want them last, change the ASC to DESC.
You have two options:
do a union
write a function and use it to order rows by
In the first case, you could do something like
select 1 as res_order, ...
...
where state like 'hi%'
union
select 2 as res_order, ...
...
where state not like 'hi%'
order by res_order asc, id desc
In the second case, you could do something like
select my_function(state, "hi") as row_order, ...
...
order by row_order
where the function returns lower values for matching states.
The code is off the top of my head: it might need some tweaking to make it runnable.