ORDER BY With possible missing column - sql

I have this DB with 2 fields, updateDate, and createDate, pretty self explanatory.
Now, my issue is that updateDate might not exist at times, and just a createDate.
I want to order by newest date, but I can't seem to find a way to order correctly, my first approach was to do the following:
ORDER BY
CASE
WHEN "updateDate" = '' THEN "createDate"
ELSE "updateDate"
END
DESC
And this partially works, it gives priority to updateDate, and then sorts by createDate.
However, the issue occurs that it gives priority to sorting by updateDate, and then by createDate (Not entirely wrong, updateDate should have priority over createDate on the same date), so if there was a createDate with no updateDate newer than the updateDates, it will be placed at the bottom anyway like this:
Item | updateDate | createDate
1 24/1/2019 1/1/2005
2 23/1/2019 1/1/2005
3 22/1/2019 1/1/2005
4 23/1/2019
5 22/1/2019
How should I do this so it sorts like this?
Item | updateDate | createDate
1 24/1/2019 1/1/2005
2 23/1/2019 1/1/2005
4 23/1/2019
3 22/1/2019 1/1/2005
5 22/1/2019
Thanks
EDIT: The SQL engine is SAP HANA, which is kind of undocumented, but from my testing, regular SQL like MySQL should work.

If you want to fall back to createDate when updateDate is missing, coalesce() might work:
SELECT * FROM TABLE ORDER BY coalesce("updateDate", "createDate");

You could use an IFNULL for order by
select *
from my_table
order by ifnull(updateDate, createDate) DESC
http://sap.optimieren.de/hana/hana/html/sql_function_ifnull.html

Try use
SELECT FIRST_VALUE(updateDate)
OVER (PARTITION BY Item ORDER BY updateDate DESC) as [last_update]

SELECT * FROM TABLE ORDER BY nvl(updateDate, createDate);
You can use this as well

Related

Turn several queries into one in SQL Server

I have a table in SQL Server called schedule that has the following columns (and others not listed):
scheduleId
roomId
dateRegistered
dateFreed
4564
2
2022-12-25
2022-12-26
4565
3
2022-12-25
2022-12-27
4566
15
2022-12-26
2022-12-27
4567
2
2022-12-28
2022-12-31
4568
3
2022-12-28
2022-12-30
In some part of my app I need to show all the rooms occupied at a certain date.
Currently I run a query like this:
SELECT TOP (1) *
FROM schedule
WHERE roomId = [theNeededRoom] AND dateFreed < [providedDate]
ORDER BY dateFreed DESC
The thing is that I have to run that query in a for loop so that I get the information for every room.
I'm sure there has to be a better way to do this in a single query that returns a row for each of the different roomIds possible, how can I go about this?
Also, when the room is first registered, the dateFreed column has a null value, if I wanted to take this into account, how can I make the query so that, in the case the dateFreed value is null, that is the row that gets chosen?
You can use TOP(1) WITH TIES, while ordering on the last "dateFreed" date.
In order to have a "tied" value to match on, instead of ordering on "dateFreed DESC" we can use the ROW_NUMBER window function to generate a ranking on the same field (which will store 1 for each most recent "dateFreed" value, per "roomId").
SELECT TOP (1) WITH TIES *
FROM schedule
WHERE dateFreed < [providedDate]
ORDER BY ROW_NUMBER() OVER(PARTITION BY roomId ORDER BY dateFreed DESC)
SELECT
t.*
FROM
(
SELECT
roomId AS rId,
max(dateFreed) AS dateFreedMax
FROM
schedule s
GROUP BY
s.roomId
) AS t
WHERE
t.dateFreedMax < [providedDate]
OR t.dateFreedMax IS NULL
Or
SELECT roomId
FROM
schedule s
GROUP BY s.roomId, dateFreed
HAVING
max(dateFreed)<[providedDate] OR dateFreed IS NULL

How to alter the position of a row with specific value in query result

Here's what I'm trying to do.
I have following sample data.
trxn_id event_id timestamp
1 4 111
1 16 121
1 1 110
Now, I'd like the event 16 to appear between 4 and 1 in the results with order by timestamp desc. Means the result should always be ordered by with time in descending, except event_id=16 row just below the row of event_id=4, no matter what it's time is.
I was thinking of selecting the event_id=4 result first then union it with the result of selecting rest of the event_id's but they don't maintain the order in which union was applied. What can be done? thanks.
Edit: I'm selecting based upon a specific trxn_id. There can be multiple event_id=16 in one trxn. All needs to appear just below the event_id=4.
I think you could predefine a hierarchy for event_id, first sort by it and then sort by TIMESTAMP DESC.
ORDER BY CASE event_id
WHEN 4
THEN 1
WHEN 16
THEN 2
WHEN 1
THEN 3
END
,TIMESTAMP DESC
In Postgres, I would recommend using arrays:
order by array_position(array[1, 16, 4], event_id), timestamp desc
Basically if you have the timestamp of 16 equal to the timestamp of 4 then you can order it by the new timestamp and event ID. There can be a shorter solution using window functions but I'm not sure if it works with postgresql
select t1.txn_id, t1.event_id, t1.timestamp, case when t2.min_time is not null then t2.min_time else t1.timestamp end as timestamp2
from table as T1
left join
(
select trxn_id, min(timestamp) as min_time
from table
group by trxn_id
) as T2
on T1.trxn_id = T2.trxn_id
and T1.event_id = 16
order by t1.txn_id, timestamp2 desc, t1.event_id, t1.timestamp desc

SQL Sever Dates in strange format in SELECT

Not sure what's going on here, hoping someone can shed some light on this.
Two queries, pretty much the same except the first only selects a date column whilst the second selects an additional column:
SELECT TOP 1 CreationDate
FROM Receipts
WHERE CreationDate IS NOT NULL
ORDER BY 1
Returns
CreationDate
1802-11-01 00:00:00.000
Second query
SELECT TOP 1 Rct_Id, CreationDate
FROM Receipts
WHERE CreationDate IS NOT NULL
ORDER BY 1
Returns
CreationDate
1994-02-14 00:00:00.000
The second one is reasonable and expected, more or less dating back to when the dataset was created. I ran a second set, changing the ORDER BY 1 DESC and got
CreationDate
5202-11-01 00:00:00.000
Rct_Id CreationDate
714350 2015-02-27 00:00:00.000
I'm just really confused as to why the date would change like this when Selected on it's own. Any ideas as to what's going on?
ORDER BY 1 is order by ordinal number, which is first column in SELECT
SELECT TOP 1 CreationDate
FROM Receipts
WHERE CreationDate IS NOT NULL
ORDER BY 1
Means take one record from table receipts ordered by CreationDate ascending.
SELECT TOP 1 Rct_Id, CreationDate
FROM Receipts
WHERE CreationDate IS NOT NULL
ORDER BY 1
Means take one record from table receipts ordered by Rct_id ascending
To get same result as first query use ORDER BY 2 or specify column name explicitly (good practice). Same applies to DESC.
SELECT TOP 1 Rct_Id, CreationDate
FROM Receipts
WHERE CreationDate IS NOT NULL
ORDER BY CreationDate /* Or ORDER BY 2 */

assigning an order ID to different rows of a table based on their Date Order and grouped by CustomerID in SQL Server 2012

I have a data set for products bought by each customer, I want to give an order to their transactions by sorting the date columns.
For example :
SubID Date other columns OrderColumn
------------------------------------------------------------------------------
1 2010/08/12 ...... ?
1 2011/09/12 ....... ?
1 2013/09/12 ...... ?
2 2013/09/12 ....... ?
2 2011/04/03 ...... ?
I want to give an order to the transactions for each customer.
Something like this :
SubID Date other columns OrderColumn
------------------------------------------------------------------------------
1 2010/08/12 ...... 1
1 2011/09/12 ....... 2
1 2013/09/12 ...... 3
2 2013/09/12 ....... 2
2 2011/04/03 ...... 1
Thanks for your help
You can use the ROW_NUMBER() windowing function:
SELECT
SubID,
[Date],
OrderColumn = ROW_NUMBER() OVER (PARTITION BY SubID ORDER BY [Date] DESC)
FROM
dbo.YourTable
This is "partition" your data by the SubID and each "partition" (or group of data) will get an incrementing number starting at 1 - based on the order date
(Side note: having a column called just Date is very unfortunate - first of all, it's not very descriptive... what kind of date are you talking about here? Furthermore, DATE is a reserved word (datatype) in SQL Server! You should strive to use something more meaningful - OrderDate or DateCreated or whatever makes sense in your situation)

SQL: how do write the ORDER BY based on value within a group?

I have a table
project issues updated
1 1 2009-09-03
1 2 2009-09-08
2 1 2009-09-12
2 2 2009-09-01
and I would like to sort so that the projects are sorted in descending order so that the project with the latest updated issue is first etc., but all issues of a project are kept together and the issues are in ascending order within the project based on issue number
the result should be:
project issues updated
2 1 2009-09-12
2 2 2009-09-01
1 1 2009-09-03
1 2 2009-09-08
Something like this should do the job:
SELECT mt.*
FROM mytable mt
JOIN (SELECT MAX(updated) AS LastUpdated, project
FROM mytable GROUP BY project) lu ON lu.project = mt.project
ORDER BY lu.LastUpdated DESC, mt.Issues
Oops, I just saw the MySQL tag. I don't know if this solution will work in MySQL
I think this would work (sorry, no mysql at hand, so I just tested on sqlite...):
select t.project, t.issues, t.updated from t
join (select project, max(updated) as dat
from t group by project) as t1
on (t.project = t1.project)
order by t1.dat desc, t.issues asc
SELECT p.project, p.issues, p.updated, max(r.updated)
FROM table p INNER JOIN table r ON r.project=p.project
GROUP BY p.project, p.issues, p.updated
ORDER BY 4 DESC, p.project, p.issues
I've tried an equivalent query in mysql & it looks like it works the way you want it to.