I'm trying to get an ordered list of rows out of my MYSQL database table based upon an integer value 'place'.
SELECT * FROM mytable
ORDER BY place;
This works okay, except that all rows with value place=0 should appear at the end of the table.
So if my table is:
name place
---- -----
John 1
Do 2
Eric 0
Pete 2
it should become:
name place
---- -----
John 1
Do 2
Pete 2
Eric 0
order by case when place = 0 then 1 else 0 end asc, place asc
that way you get all the non-zeroes ordered first.
SELECT *
FROM myTable
ORDER BY place>0 DESC, place
is a solution without CASE
SELECT *
FROM myTable
ORDER BY CASE place WHEN 0 THEN 9999 ELSE place END
This approach implies that we known that 9999 (or some other value) is bigger than all possible values in the place column.
Alternatively we can sort by two values as in:
ORDER BY CASE place WHEN 0 THEN 0 ELSE -1 END, place
Related
I have data which contains 1000+ lines and in this it contains errors people make. I have added a extra column and would like to find all duplicate Rev Names and give the first one a 1 and all remaining duplicates a 0. When there is no duplicate, it should be a 1. The outcome should look like this:
RevName ErrorCount Duplicate
Rev5588 23 1
Rev5588 67 0
Rev5588 7 0
Rev5588 45 0
Rev7895 6 1
Rev9065 4 1
Rev5588 1 1
I have tried CASE WHEN but its not giving the first one a 1, its giving them all zero's.
Thanks guys, I am pulling out my hair here trying to get this done.
You could use a case expression over the row_number window function:
SELECT RevName,
Duplicate,
CASE ROW_NUMER() OVER (PARTITION BY RevName
ORDER BY (SELECT 1)) WHEN 1 THEN 1 ELSE 0 END AS Duplicate
FROM mytable
SQL tables represent unordered sets. There is no "first" of anything, unless a column specifies the ordering.
Your logic suggests lag():
select t.*,
(case when lag(revname) over (order by ??) = revname then 0
else 1
end) as is_duplicate
from t;
The ?? is for the column that specifies the ordering.
I have a table that has demographic information about a set of users which looks like this:
User_id Category IsMember
1 College 1
1 Married 0
1 Employed 1
1 Has_Kids 1
2 College 0
2 Married 1
2 Employed 1
3 College 0
3 Employed 0
The result set I want is a table that looks like this:
User_Id|College|Married|Employed|Has_Kids
1 1 0 1 1
2 0 1 1 0
3 0 0 0 0
In other words, the table indicates the presence or absence of a category for each user. Sometimes the user will have a category where the value if false, sometimes the user will have no row for a category, in which case IsMember is assumed to be false.
Also, from time to time additional categories will be added to the data set, and I'm wondering if its possible to do this query without knowing up front all the possible category names, in other words, I won't be able to specify all the column names I want to count in the result. (Note only user 1 has category "has_kids" and user 3 is missing a row for category "married"
(using Postgres)
Thanks.
You can use jsonb funcions.
with titles as (
select jsonb_object_agg(Category, Category) as titles,
jsonb_object_agg(Category, -1) as defaults
from demog
),
the_rows as (
select null::bigint as id, titles as data
from titles
union
select User_id, defaults || jsonb_object_agg(Category, IsMember)
from demog, titles
group by User_id, defaults
)
select id, string_agg(value, '|' order by key)
from (
select id, key, value
from the_rows, jsonb_each_text(data)
) x
group by id
order by id nulls first
You can see a running example in http://rextester.com/QEGT70842
You can replace -1 with 0 for the default value and '|' with ',' for the separator.
You can install tablefunc module and use the crosstab function.
https://www.postgresql.org/docs/9.1/static/tablefunc.html
I found a Postgres function script called colpivot here which does the trick. Ran the script to create the function, then created the table in one statement:
select colpivot ('_pivoted', 'select * from user_categories', array['user_id'],
array ['category'], '#.is_member', null);
I have this table
id value
1 OK
2 xminimum
3 NO
4 YES
I want to sort this table by value where minimum is always first then the rest according to alphabetic order of value column
Meaning:
xminimum
NO
OK
YES
I wrote this query:
Select *
from table_a
order by case when value='xminimum' then 1 else ????? end
I don't know what to put in the else... conceptually it should be else value end so it means alphabetic order.. but I can not combine integer with text.
How do I fix it?
As requested, copied from my comment:
Select *
from table_a
order by case when value='xminimum' then 1 else 2 end, value
Another solution:
SELECT *
FROM table_a
ORDER BY value <> 'xminimum', value;
Do it like you have and add the value column as second column to sort by:
SELECT *
FROM table_a
ORDER BY CASE WHEN value='xminimum' THEN 1 ELSE 2 END, value
I took this query from this question.
SELECT *
FROM A
WHERE x='abc'
OR y=0
order by case when x='abc' then 0 else 1 end;
This query supposedly will prioritize x='abc' cases. But I'm really confused why is this happening? Isn't ORDER BY followed by a column name or column number? Also, I researched on the syntax of ORDER BY and they don't tell anything about this. I also tried something like this but it says: "1st ORDER BY term out of range - should be between 1 and 1":
SELECT A
FROM B
ORDER BY 2
So, can anyone explain this query or at least point to a good documentation? Thank you very much.
Well, when an ORDER BY clause is followed by a number, this number will be referenced to the column in the (number) position.
The ORDER BY followed by a CASE EXPRESSION is called conditional ordering, each column will get the value 0 when x is equal to abc and when its not it will get the value 1. After that, the ordering is in ASC , so 0 will always be prioitized before 1.
It will be something like this:
x | y | .... | Here is the new value that will order the query
abc 1 0
ayr 0 1
acz 1 1
.........
So, basically it's like generating a new value.
I have a (int) column called "priority". When I select my items I want the highest priority (lowest number) to be first, and the lowest priority (highest number) to be the last.
However, the items without a priority (currently priority 0) should be listed by some other column after the ones with a priority.
In other words. If I have these priorities:
1 2 0 0 5 0 8 9
How do I sort them like this:
1 2 5 8 9 0 0 0
I guess I could use Int.max instead of 0, but 0 makes up such a nice default value which I would try to keep.
I don't think it can get cleaner than this:
ORDER BY priority=0, priority
SQLFiddle Demo
Note that unlike any other solutions, this one will take advantage of index on priority and will be fast if number of records is large.
Try:
order by case priority when 0 then 2 else 1 end, priority
A very simple solution could be to use a composite value/ "prefix" for sorting like this:
SELECT ...
FROM ...
ORDER By CASE WHEN priority = 0 THEN 9999 ELSE 0 END + priority, secondSortCriteriaCol
This will do the trick. You will need to replace testtable with your table name.
SELECT t.priority
FROM dbo.testtable t
ORDER BY (CASE WHEN t.priority = 0 THEN 2147483647 ELSE t.priority END)
In case it's not clear I've picked 2147483647 because this is the max value of the priority column so it will be last.
Mark's answer is better and defo one to go with.
order by case(priority) when 0 then 10 else priority end