ORDER BY FIELD() not in - sql

I have a set of records which I need to sort in particular order. Basically I need to sort like:
select * from Table
ORDER BY FIELD(code, 'int', (<> 'int' and <> 'nat'), 'nat')
Or
select * from Table
ORDER BY FIELD(id, 5, >= 10, 7)
How can I do it?

I think this conditional sorting meets your requirement:
select * from Table
order by case
when id = 5 then 1
when id >= 10 then 2
when id = 7 then 3
else 4
end
or for the 1st case:
select * from Table
order by case
when code = 'int' then 1
when code <> 'nat' then 2
else 3
end

From your second select statement, You can try -
select * from Table
ORDER BY CASE WHEN id = 5 THEN 1
WHEN id BETWEEN 6 AND 10 AND id NOT <> 7 THEN 2
WHEN id = 7 THEN 3 END)

You can also use multiple keys in order by:
order by (id = 5) desc, -- "5" first
(id = 7) asc -- "7" last
I am using MySQL syntax because FIELD() is a MySQL function.

Related

SQL Group By and assign highest a value

I am struggling with the SQL (mssql) to manipulate my data as i need it. I have a table like this;
SOMEID, SOMEFIELD, DATE
5 True 01-01-2010
5 True 01-01-2011
5 False 05-05-2012
7 True 05-05-2011
7 False 06-07-2015
What I am trying to achieve is to add another column which assigns the value 1 if they are the most recent for that ID, and 0 if not. So in the above data example the new column values from top to bottom would be 0, 0, 1, 0, 1.
I know I need to group by date but am having trouble assigning the values.
Thanks for any pointers!
You can use row_number() in SQL Server like this:
select *
, case when (row_number() over (partition by SOMEID order by [Date] desc)) = 1 then 1 else 0 end seq
from
yourTable
order by
SOMEID, [Date];
SQL Fiddle Demo
You can use a self join to get the highest row per group then in update query use a case statement to assign value to new column
update a
set a.[somecol] = case when b.[SOMEID] is null then 1 else 0 end
from demo a
left join demo b on a.[SOMEID] = b.[SOMEID]
and a.[DATE] < b.[DATE]
DEMO
try this
SELECT SOMEID, SOMEFIELD, DATE
, CASE WHEN (SELECT MAX(SubTab.Date)
FROM myTable SubTab
WHERE SubTab.SOMEID = myTable.SOMEID
) = myTable.DATE
THEN 1 ELSE 0 END
FROM myTable

SQL Case on Where clause to different columns

I've been trying to get a query that, based on a given condition (if isCurrent = 1 or not) should give me just one value/row based on the CurriculumId /which will be a parameter on a stored procedure).
This value should, in case isCurrent = 1 return to me the item with the most current StartDate but if isCurrent = 0 then it should give me the one with the most current EndDate.
The thing is that I only want one item per CurriculumId, ideally the one with isCurrent = 1 and the most current StartDate (ignoring the remaining rows) but, if there are no experiences with isCurrent = 1, then it should return to me the one with the most current EndDate.
My previous query was almost working but I still got the one with the most current StartDate (isCurrent = 1) AND the one with the most current EndDate when I want to retrieve just one or another.
I've come to the query bellow:
SELECT table.IntProfessionalExperienceId,
table.IsCurrent,
table.StartDate,
table.EndDate
FROM table
WHERE table.CurriculumId = 12
AND
CASE table.IsCurrent
WHEN 1
THEN
table.StartDate = (
SELECT max(table.StartDate)
FROM table
WHERE table.IsCurrent = 1
AND table.CurriculumId = 12
GROUP BY table.CurriculumId
)
ELSE
table.EndDate = (
SELECT max(table.EndDate)
FROM table
WHERE table.CurriculumId = 12
GROUP BY table.CurriculumId
)
END
Individually, the queries seem to be working OK and returning the supposed value although when ran as a whole I get the following errors:
Msg 102, Level 15, State 1, Line 8
Incorrect syntax near '='.
Msg 102, Level 15, State 1, Line 14
Incorrect syntax near ')'.
Msg 102, Level 15, State 1, Line 21
Incorrect syntax near ')'.
What in my syntax is wrong? I know from reading the errors what is wrong with the query but I just don't know how to fix it. And is it just the syntax or am I doing the query wrong to start with?
Split this into multiple conditions, like this:
SELECT
table.IntProfessionalExperienceId,
table.IsCurrent,
table.StartDate,
table.EndDate
FROM table
WHERE
table.CurriculumId = 12 AND
(
(
Table.IsCurrent = 1 AND
table.StartDate =
(
SELECT max(table.StartDate)
FROM table
WHERE
table.IsCurrent = 1 AND
table.CurriculumId = 12
GROUP BY table.CurriculumId
)
) OR
(
ISNULL(table.IsCurrent,0) != 1 AND
table.EndDate =
(
SELECT max(table.EndDate)
FROM table
WHERE table.CurriculumId = 12
GROUP BY table.CurriculumId
)
)
)
EDIT: another, arguably simpler approach would be to pre-aggregate the data you want in your WHERE clause so that you only need to call it a single time, rather than evaluate each row separately. Something like the following:
SELECT
table.IntProfessionalExperienceId,
table.IsCurrent,
table.StartDate,
table.EndDate
FROM
table
INNER JOIN
(
SELECT
MAX(table.EndDate) AS MaxEndDate,
MAX(CASE WHEN table.IsCurrent = 1 THEN table.StartDate END) AS MaxCurrentStartDate
FROM table
WHERE CurriculumID = 12
) MaxDates ON
(Table.IsCurrent = 1 AND Table.StartDate = MaxDates.MaxCurrentStartDate) OR
(ISNULL(Table.IsCurrent, 0) != 1 AND Table.EndDate = MaxDates.MaxEndDate)
WHERE
table.CurriculumId = 12
Give each row a rank in its curriculumid group, using ROW_NUMBER with an appropriate order by clause. Then only take the records ranked 1 (i.e. best matching).
select
intprofessionalexperienceid,
iscurrent,
startdate,
enddate
from
(
select mytable.*
row_number() over
(
partition by curriculumid
order by
case when iscurrent = 1 then 1 else 2 end,
case when iscurrent = 1 then startdate else enddate end desc
) as rn
from mytable
) ranked
where rn = 1;
(I know this doesn't actually answer your question, but is the straight-forward way to approach the problem in my opinion.)
Try to use CASE statemen this way:
SELECT table.IntProfessionalExperienceId,
table.IsCurrent,
table.StartDate,
table.EndDate
FROM table
WHERE table.CurriculumId = 12
AND table.EndDate = CASE
WHEN table.IsCurrent = 1
THEN (
SELECT max(table.StartDate)
FROM table
WHERE table.IsCurrent = 1
AND table.CurriculumId = 12
GROUP BY table.CurriculumId
)
ELSE
(
SELECT max(table.EndDate)
FROM table
WHERE table.CurriculumId = 12
GROUP BY table.CurriculumId
)
END

Order by inside Case in Order By

I have this database
ID Title
1 Unassaign
6 Prima
7 Adi
I want to make ID 1 to be display last but the other are sort by their title
Desired results:
ID Title
7 Adi
6 Prima
1 Unassaign
This is my code:
SELECT a.ID_WB, a.TITLE, a.DESCRIPTION, a.AUTHOR, a.DATECREATE, a.DATEUPDATE
FROM WORKBOOK a
order by case when ID_WB = 1 then 1
else 0 end
I tried insert Order By after else but it always return SQL error..
Is there a workaroud to this problem?
Thanks
PS: The first Order byshould sort by ID
Use two expressions in the order by:
order by (case when ID_WB = 1 then 1 else 0 end), title

Select rows using a count condition inside a where clause

There is a table, MyTable(ID, Type, Date). Column 'Type' can have a value of 1 or 2.
Top 'x' rows, ordered by 'Date' and satisfying the following condition, have to be selected.('a' and 'b' are integer values)
The selected 'x' rows can contain only a maximum of 'a' Type 1 rows and 'b' Type 2 rows.(If a+b < x, then only a+b rows have to be selected.)
I might be completely wrong but I have an idea of doing this by having count() inside a WHERE clause. But I am not sure of how to do it.
How do I go about this problem?
UPDATE:
Example -
x = 5
Case 1:
a = 5, b = 5
Result: Rows 1,2,3,4,5
Case 2:
a = 4, b = 1
Result: Rows 1,2,4,6,8
Case 3:
a = 1, b = 5
Result: Rows 1,2,3,5,7
Case 4:
a = 2, b = 1
Result: Rows 1,2,4
You can do it by nesting a UNION inside another query:
select top #x *
from (
select top #a *
from table
where type = '1'
order by [date]
union
select top #b *
from table
where type = '2'
order by [date]
) t
order by [date]

Select rows until condition met

I would like to write an Oracle query which returns a specific set of information. Using the table below, if given an id, it will return the id and value of B. Also, if B=T, it will return the next row as well. If that next row has a B=T, it will return that, and so on until a F is encountered.
So, given 3 it would just return one row: (3,F). Given 4 it would return 3 rows: ((4,T),(5,T),(6,F))
id B
1 F
2 F
3 F
4 T
5 T
6 F
7 T
8 F
Thank you in advance!
Use a sub-query to find out at what point you should stop, then return all row from your starting point to the calculated stop point.
SELECT
*
FROM
yourTable
WHERE
id >= 4
AND id <= (SELECT MIN(id) FROM yourTable WHERE b = 'F' AND id >= 4)
Note, this assumes that the last record is always an 'F'. You can deal with the last record being a 'T' using a COALESCE.
SELECT
*
FROM
yourTable
WHERE
id >= 4
AND id <= COALESCE(
(SELECT MIN(id) FROM yourTable WHERE b = 'F' AND id >= 4),
(SELECT MAX(id) FROM yourTable )
)