SQL Sever Dates in strange format in SELECT - sql

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 */

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

SQL - JOIN 2 tables with either NULL OR MAX

I have two tables in Teradata that i need to LEFT JOIN.
The first one includes clients, the second their details with the validity end date. NULL represents currently valid.
Table1
client_id
1
2
Table2
client_id
valid_end
1
31.12.2021
1
31.12.2022
2
31.12.2020
2
null
I need to left join the two tables using the most recent record for each client from Table2.
In case there is a currently valid record with NULL, it is used. If there is not any NULL record, the highest date is used.
Result
client_id
valid_end
1
31.12.2022
2
null
Tried a lot using QUALIFY and MAX, but never reached the requested result. Thanks for advice.
Use ROW_NUMBER instead of MAX, NULLS FIRST sorts NULL before the highest date:
qualify
row_number()
over (partition by client_id
order by valid_end desc NULLS FIRST) = 1

ORDER BY With possible missing column

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

Select most recent InstanceID base on max end date

I am trying to pull the memberinstance from a table based on the max DateEnd. If it is Null I want to pull that as it would be still ongoing. I am using sql server.
select memberinstanceid
from table
group by memberid
having MAX(ISNULL(date_end, '2099-12-31'))
This query above doesnt work for me. I have tried different ones and have gotten it to return the separate instances, but not just the one with the max date.
Below is what my table looks like.
MemberID MemberInstanceID DateStart DateEnd
2 abc12 2013-01-01 2013-12-31
4 abc21 2010-01-01 2013-12-31
2 abc10 2015-01-01 NULL
4 abc19 2014-01-01 2014-10-31
I would expect my results to look like this
MemberInstanceID
abc10
abc19
I have been trying to figure out how to do this but have not had much luck. Any help would be much appreciated. Thanks
I think you need something like the following:
select MemberID, MemberInstanceID
from table t
where (
-- DateEnd is null...
DateEnd is null
or (
-- ...or pick the latest DateEnd for this member...
DateEnd = (
select max(DateEnd)
from table
where MemberID = t.MemberID
)
-- ... and check there's not a NULL entry for DateEnd for this member
and not exists (
select 1
from table
where MemberID = t.MemberID
and DateEnd is null
)
)
)
The problem with this approach would be if there are multiple rows that match for each member, i.e. multiple NULL rows with the same MemberID, or multiple rows with the same DateEnd for the same MemberID.
SELECT TOP 1 memberinstanceid
from table
ORDER BY (CASE WHEN [DateEnd] IS NULL THEN 1 ELSE 0 END) DESC,
[DateEnd] DESC
The ORDER BY is essentially creating a "column" to sort the NULL values to the top, then doing a secondary sort on the dates that are not null.
You have a good start but you don't need to perform any explicit grouping. What you want is the row where the EndDate is null or is the largest value (latest date) of all the records with the same MemberID. You also realized that the Max couldn't return the latest non-null date because the null, if one exists, must be the latest date.
select m.*
from Members m
where m.DateEnd is null
or m.DateEnd =(
select Max( IsNull( DateEnd, '9999-12-31' ))
from Members
where MemberID = m.MemberID );

How to increment a value in SQL based on a unique key

Apologies in advance if some of the trigger solutions already cover this but I can't get them to work for my scenario.
I have a table of over 50,000 rows, all of which have an ID, with roughly 5000 distinct ID values. There could be 100 rows with an instrumentID = 1 and 50 with an instrumentID = 2 within the table etc but they will have slightly different column entries. So I could write a
SELECT * from tbl WHERE instrumentID = 1
and have it return 100 rows (I know this is easy stuff but just to be clear)
What I need to do is form an incrementing value for each time a instrument ID is found, so I've tried stuff like this:
IntIndex INT IDENTITY(1,1),
dDateStart DATE,
IntInstrumentID INT,
IntIndex1 AS IntInstrumentID + IntIndex,
at the table create step.
However, I need the IntIndex1 to increment when an instrumentID is found, irrespective of where the record is found in the table so that it effectively would provide a count of the records just by looking at the last IntIndex1 value alone. Rather than what the above does which is increment on all of the rows of the table irrespective of the instrumentID so you would get 5001,4002,4003 etc.
An example would be: for intInstruments 5000 and 4000
intInstrumentID | IntIndex1
--------- ------------------
5000 | 5001
5000 | 5002
4000 | 4001
5000 | 5003
4000 | 4002
The reason I need to do this is because I need to join two tables based on these values (a start and end date for each instrumentID). I have tried GROUP BY etc but this can't work in both tables and the JOIN then doesn't work.
Many thanks
I'm not entirely sure I understand your problem, but if you just need IntIndex1 to join to, could you just join to the following query, rather than trying to actually keep the calculated value in the database:
SELECT *,
intInstrumentID + RANK() OVER(PARTITION BY intInstrumentID ORDER BY dDateStart ASC) AS IntIndex1
FROM tbl
Edit: If I understand your comment correctly (which is not certain!), then presumably, you know that your end date and start date tables have the exact same number of rows, which leads to a one to one mapping between them based on thir respective end dates within instrument id?
If that's the case then maybe this join is what you are looking for:
SELECT SD.intInstrumentID, SD.dDateStart, ED.dEndDate
FROM
(
SELECT intInstrumentID,
dStartDate,
RANK() OVER(PARTITION BY intInstrumentID ORDER BY dDateStart ASC) AS IntIndex1
FROM tblStartDate
) SD
JOIN
(
SELECT intInstrumentID,
dEndDate,
RANK() OVER(PARTITION BY intInstrumentID ORDER BY dEndDate ASC) AS IntIndex1
FROM tblStartDate
) ED
ON SD.intInstrumentID = ED.intInstrumentID
AND SD.IntIndex1 = ED.IntIndex1
If not, please will you post some example data for both tables and the expected results?