How to retrieve list from SQL alphabetically except one item? - sql

I have a table with a column for Occupations in a table in SQL. Along with a few occupations, I also have an item for 'others'. I will display these in a dropdownlist and on selecting 'others' I will show a text box.
Ex: Business
Student
Employee
Others
I want to retrieve the list in Ascending Order, but when I do that using ORDER BY ASC 'Others' will come somewhere in between. I want it to be at the end of the list being returned.
Like Business
Employee
Student
Other
Please suggest a solution to keep the Others at the end of list while retrieving.
(Note: The list is dynamic and will be changing , so I cannot hardcode)

Try something like
SELECT * FROM
(
SELECT *,
CASE WHEN <YourValue> = 'Others' THEN 1 ELSE 0 END AS PrimaryOrder
FROM <YourTable>
) AS SubQuery01
ORDER BY PrimaryOrder, YourOrderByCriteria

A possible solution:
select occupations from mytable where occupations != 'Others' order by 1 ASC
union
select occupations from mytable where occupations == 'Others';
but it's overkill, you can add others by hand

I have tried out a solution and is working for me..
SELECT O.NAME FROM OCCUPATIONTABLE O
ORDER BY CASE
WHEN O.NAME = 'Others'
THEN 1
ELSE 0
END ASC
,O.NAME ASC

Related

Select Case is not working with Order by

I was using a simple sql query and getting an ordered list, but when I changed some of the values in the column I'm sorting by, those rows were no longer being sorted correctly.
select distinct u.Email,
case
when l.region_id is null then 'EU'
else l.region_id
end
as Location
from TB_User u
left join cat..location l on l.location=u.Location
where u.Username in (....)
order by l.region_id
I have about 5 rows that returned null for their region_id so they would be at the top of the result set. When I added the case and replaced their value, they still remain at the top. Is there anyway to make these rows sort according to their given value?
You can use CASE also in the ORDER BY. But in this case it seems that you instead want to order by the column which uses the CASE.
ORDER BY Location
If you instead want the null-regions at the bottom:
ORDER BY CASE WHEN l.region_id is null THEN 0 ELSE 1 END DESC,
Location ASC
If your rdbms doesn't support this (like SQL-Server does) you have to repeat it:
ORDER BY CASE WHEN l.region_id IS NULL THEN 'EU' ELSE l.region_id END ASC
You just order by the column value, which is null.
If you want to order by the case statement, just copy it in the order by clause:
order by
case
when l.region_id is null then 'EU'
else l.region_id end
If you are using SQL, try within the SELECT statement, use:
ISNULL(l.region_id, 'EU') AS Location
and then
ORDER BY 2
This will make your query:
SELECT DISTINCT u.Email, ISNULL(l.region_id, 'EU') AS Location
FROM TB_User u
LEFT JOIN cat..location l ON l.location=u.Location
WHERE u.Username in (....)
ORDER BY 2

Select an ID if count is equal to 1

I am trying to write a query which needs to find an ID number from 3 WHERE values based on the result only being equal to 1.
So say i want to find a patient's ID and my where clause matches the firstname, lastname and DOB. If there are 2 results because of duplicates, i need the output to be NIL else it should return the patient ID.
if(select count(*)
from patient
where last_name = 'JAMES'
and first_name = 'JONES'
and birth_DtTM = '1980-01-01') > 1
print 'NULL' else return Pat_ID1
This is kind of what i am leading towards.
Thanks guys
select case when count(*)> 1
then 'NULL' else Pat_ID1 end
from patient
where last_name = 'JAMES'
and first_name = 'JONES'
and birth_DtTM = '1980-01-01'
group by Pat_ID1
try below.
;WITH CTE(Pat_ID1,last_name,first_name,birth_DtTM,dup_rows)
as
(
SELECT Pat_ID1,last_name,first_name,birth_DtTM,ROW_NUMBER() OVER(PARTITION BY last_name,first_name,birth_DtTM ORDER BY Pat_ID1) AS dup_rows FROM patient
)
SELECT
case when dup_rows>1 then null
when dup_rows=1 then Pat_ID1
end
FROM CTE
You can do it like this:
SELECT
PatientID = CASE COUNT(*) WHEN 1 THEN MAX(Pat_ID1) END
FROM
patient
WHERE
last_name = 'JAMES'
AND first_name = 'JONES'
AND birth_DtTM = '1980-01-01'
;
The CASE expression will evaluate either to the single Pat_ID1 matching the request or to NULL (if COUNT(*) is anything but 1).
As you can see, the Pat_ID1 value is obtained with the help of an aggregate function (by the way, you can use MIN instead of MAX just as well). This is because the presence of COUNT(*) in the query automatically implies grouping and now, if you want to reference columns of the underlying row set, you must only access their aggregated values.

SQL Specific Order

Given the following query:
SELECT DISTINCT n.iswinner, i.name
FROM nominees n, institutions i
WHERE n.iid = i.iid and n.filmname = '127 Hours'
ORDER BY name
I get the output:
iswinner name
NULL academy awards
NULL baftas
NULL critics' choice awards
NULL golden globes
NULL screen actors guild
NULL writers guild of america
I am trying to figure out if it is possible to order this output in a more specific manner. The order I am looking for is to list first 'academy awards', then 'golden globes' then anything with a 'guild' in its name, and finally anything else alphabetically. So therefore the output I'm looking for is more along the lines of this:
iswinner name
NULL academy awards
NULL golden globes
NULL screen actors guild
NULL writers guild of america
NULL bafta
NULL critics' choice awards
Is there a way to do such a thing? I believe I should use something like CASE, but I couldn't seem to figure out the correct syntax for it. Thanks for any help.
Yes there is a way to do something like this and just like you thought, you can do this with a CASE statement. Something like the following should do the trick:
SELECT
DISTINCT n.iswinner,
i.name,
CASE
WHEN i.name = 'academy awards' THEN 1
WHEN i.name = 'golden globes' THEN 2
WHEN i.name like '%guild%' THEN 3
ELSE 4
END AS Order
FROM nominees n, institutions i
WHERE n.iid = i.iid and n.filmname = '127 Hours'
ORDER BY
Order,
i.name
So, to give you a little more information on what is being done here. In the ORDER clause, we're ordering by a CASE statement. Basically, based upon what the i.name field is, we are assigning an integer number to order by. academy awards is assigned 1, golden globes is assigned 2, anything that contains 'guild' is assigned 3, and anything else is assigned 4. So we first order by this CASE statement (which gives the specific ordering you want) and then order by the name field which will satisfy your the second requirement of ordering anything else by name (which we previously assigned the value of 4 in the CASE statement for ordering).
I hope this makes sense to you.
Same query using GROUP BY rather than DISTINCT:
SELECT
n.iswinner,
i.name
FROM nominees n, institutions i
WHERE n.iid = i.iid and n.filmname = '127 Hours'
GROUP BY
n.iswinner,
i.isname
ORDER BY
CASE
WHEN i.name = 'academy awards' THEN 1
WHEN i.name = 'golden globes' THEN 2
WHEN i.name like '%guild%' THEN 3
ELSE 4
END,
i.name
order by
case
when name = 'academy awards' then 1
when name = 'golden globes' then 2
when name like '%guild%' then 3
else 4
end
, name
No need for a case clause. SQL Fiddle
select *
from (
select distinct n.iswinner, i.name
from nominees n, institutions i
where n.iid = i.iid and n.filmname = '127 Hours'
) s
order by
name != 'academy awards',
name != 'golden globes',
name not like '%guild%',
name
false orders before true

Adjust SQL Query to force a record to appear first?

How can the below query be adjusted to return always the member with MemberID = 'xxx' as the first row
SELECT * FROM Members
select * from Members
order by case when MemberID = XXX then 0 else 1 end
This should work and it will also allow you to order the remaining items by MemberID (Assuming xxx=12 in this example)
SELECT *
FROM Members
ORDER BY CASE WHEN MemberID=12 THEN NULL ELSE isnull(MemberID,0) END
If the memberID column can't contain nulls, you can get away with this which might perform slightly better.
SELECT *
FROM Members
ORDER BY CASE WHEN MemberID=12 THEN NULL ELSE MemberID END
SELECT
CASE WHEN MemberID = 'xxx' AS 1 ELSE 0 END CASE AS magic,
*
FROM Members
ORDER BY magic DESC
The syntax might vary depending on yr db, but I hope you get the idea.
SELECT * FROM `Members` WHERE `MemberID` = '[ID]' LIMIT 1 UNION SELECT * FROM `Members`
This should work. Tested on my database instance. Chosen ID is always first.
A more robust solution, if you have more than one record that has to be floated to the top, or if you have a specific order for multiple records, is to add a ResultsOrder column to your table, or even another table MemberOrder(memberid, resultorder). Fill resultorder with big numbers and ...
Select m.*
From Members m
Left Join MemberOrder mo on m.MemberID=mo.MemberID
Order by coalesce(mo.resultorder, 0) DESC
try this:
SELECT * FROM Members
ORDER BY IF(x.MemberId = XXX, -1, ABS(x.MemberId))

sql query with a case when returning more than one row

I'm trying to do a query with a case when condition to see what list I will show but I'm having this error ORA-01427: single-row subquery returns more than one row.
the query is this:
SELECT
CASE WHEN action_type like 'Trigger Severity' THEN (select cast(SEVERITY as varchar2(255)) name from SURV_TRIGGER_SEVERITY_LIST)
WHEN action_type like 'Host Group' then (select cast(name as varchar2(255)) name from Surv_List.groups)
WHEN action_type like 'Host' then (select cast(name as varchar2(255)) name from tn_tree)
END display_value
FROM surv_action_type_list
WHERE id = 0
is it possible to call a query with more than one row inside a case condition?
I would do this in multiple steps. Get the action type, then issue the appropriate query. Whether you have this logic at the front end or in a stored procedure is up you and probably depends on a lot of other things.
If you absolutely needed to do it this way, then you could try something like this:
SELECT
SQ.display_value
FROM
surv_action_type_list SATL
INNER JOIN
(
SELECT
'Trigger Severity' action_type,
CAST(severity AS VARCHAR2(255)) display_value
FROM
SURV_TRIGGER_SEVERITY_LIST
UNION ALL
SELECT
'Host Group' action_type,
CAST(name AS VARCHAR2(255) display_value
FROM
Surv_List.groups
UNION ALL
SELECT
'Host' action_type,
CAST(name AS VARCHAR2(255) display_value
FROM
tn_tree
) SQ ON
SQ.action_type = SATL.action_type
WHERE
SATL.id = 0
You have 3 sub-queries.
1. select cast(SEVERITY as varchar2(255)) name from SURV_TRIGGER_SEVERITY_LIST
2. select cast(name as varchar2(255)) name from Surv_List.groups
3. select cast(name as varchar2(255)) name from tn_tree
Each one must return 0 or 1 rows but not more.
No. Your subquery should return only one value (only one row and one column) since you'll display it on a single row.
Since you are displaying the value as one column using your query above, it looks like your intention is to get only one value.
select
CASE WHEN action_type like 'Trigger Severity' THEN (select cast(SEVERITY as varchar2(255)) name from SURV_TRIGGER_SEVERITY_LIST)
WHEN action_type like 'Host Group' then (select cast(name as varchar2(255)) name from Surv_List.groups)
WHEN action_type like 'Host' then (select cast(name as varchar2(255)) name from tn_tree)
END display_value
from surv_action_type_list
where id = 0
Is there a where missing that links this ID to say a Severity list?
Usually queries like this would have a condition in the subquery.. something like..
select
CASE WHEN action_type like 'Trigger Severity'
THEN (select cast(SEVERITY as varchar2(255)) name
**from SURV_TRIGGER_SEVERITY_LIST trglst
where trglst.name = lst.severity_name**
-----
---
END display_value
from surv_action_type_list lst
where id = 0