Capture a Value in SQL - sql

I want to capture the last value recorded right before a certain time was recorded. In Healthcare terms I need the max flowsheet value 0-10 that was recorded right before a pain medication was given.
I can add the max(flowsheet recorded time) but I am not sure how to add in the time of the medication so I get the max value that was recorded.

I want to capture the last value recorded right before a certain time was recorded. In Healthcare terms I need the max flowsheet value 0-10 that was recorded right before a pain medication was given.
We know little about your database, so here is the general approach. You want to look at rows before the medication (where mydate < medication_date). Of these rows, you say you to want the maximum flowsheet value (max(flowsheet)).
Furthermore, in your request comments you say the medication_date is in another table.
Putting these things together we get something like:
select max(flowsheet)
from mytable
where mydate < (select medication_date from medication);
Well, the medication table won't really have just one row with the global medication date. So let's assume both tables refer to patients, and you want the information for a particular patient. This would be something like this:
select max(flowsheet)
from mytable t
where patient_id = 12345
and mydate <
(
select medication_date
from medication m
where m.patient_id = t.patient_id
);

Related

TSQL query to find latest (current) record from period column when there are past present and future records

edited as requested:
My apologies. I've been dealing with this a bit and it's well and truly in my head, but not for the reader.
We have multiple records in table A which have multiple entries in the Period column. Say it's like a football schedule. Teams will have multiple dates/times in the Period column.
When we run query:
We want records selected for the most recent games only.
We don't want the earlier games.
We don't want the games "scheduled" and not yet played.
"Last game played" i.e. Period for teams are often on different days.
Table like:
Team Period
Reds 2021020508:00
Reds 2021011107:00
City 2021030507:00
Reds 2021032607:00
City 2021041607:00
Reds 2021050707:00
When I run query, I want to see the records for last game played regardless of date. So if I run the query on 27 Mar 2021, I want:
City 2021030507:00
Reds 2021032607:00
Keep in mind I used the above as an easily understandable example. In my case I have 1000s of "Teams" each of which may have 100+ different date entries in the Period column and I would like the solution to be applicable regardless of number of records, dates, or when the query is run.
What can I do?
Thanks!
So this gives you your desired output using the sample data, does it fulfil your requirement?
create table x (Team varchar(10), period varchar(20))
insert into x values
('Reds','2021020508:00'),
('Reds','2021011107:00'),
('City','2021030507:00'),
('Reds','2021032607:00'),
('City','2021041607:00'),
('Reds','2021050707:00')
select Team, Max(period) LastPeriod
from x
where period <=Format(GetDate(), 'yyyyMMddhh:mm')
group by Team
The string-formatted date you have order by text, so I think this would work
SELECT TOP 2 *
FROM tableA
WHERE period = FORMAT( GETDATE(), 'yyyyMMddhh:mm' )
ORDER BY period
Perhaps you want:
where period = (select max(t2.period) from t t2)
This returns all rows with the last period in the table.

SQL: Find nth order for nth customer

I am quite new to SQL, have been learning for ~3 weeks, and have taken a liking to it. Hoping to polish up my skills before beginning to apply to Data Analyst roles.
I've been working with a dummy dvd-rental database and have found myself unable to solve a challenge given to me by a peer. The question was: "what is the most expensive rental for the 4th customer?"
We can see in picture, that based on the nth_customer column, Terrance Roush is the 4th ever customer (he's the 4th ever person to pay). But the issue is that the nth_customer column is actually reporting back the nth order and continues counting to infinity. So the next time Terrance shows up, the nth_customer column will not show '4' (which is what I was hoping to achieve).
Would appreciate any feedback on how to solve this. Thank you in advance.
If "the fourth customer" means the customer who did the fourth rental, you can break the problem down into two - finding that fourth customer, and finding their most expensive rental. Something like this:
SELECT *
FROM payment
WHERE customer_id = (
SELECT customer_id
FROM payment
ORDER BY payment_date
LIMIT 1 OFFSET 3
)
ORDER BY amount DESC
LIMIT 1;
Here I'm finding the ID of the fourth customer in the subquery, using a LIMIT & OFFSET to get just the one record I want. Then in the outer query I'm simply ordering all of that customer's records and taking the one with the biggest amount.

GROUP BY with date range

I have a table with 4 columns, id, Stream which is text, Duration (int), and Timestamp (datetime). There is a row inserted for every time someone plays a specific audio stream on my website. Stream is the name, and Duration is the time in seconds that they are listening. I am currently using the following query to figure up total listen hours for each week in a year:
SELECT YEARWEEK(`Timestamp`), (SUM(`Duration`)/60/60) FROM logs_main
WHERE `Stream`="asdf" GROUP BY YEARWEEK(`Timestamp`);
This does what I expect... presenting a total of listen time for each week in the year that there is data.
However, I would like to build a query where I have a result row for weeks that there may not be any data. For example, if the 26th week of 2006 has no rows that fall within that week, then I would like the SUM result to be 0.
Is it possible to do this? Maybe via a JOIN over a date range somehow?
The tried an true old school solution is to set up another table with a bunch of date ranges that you can outer join with for the grouping (as in the other table would have all of the weeks in it with a begin / end date).
In this case, you could just get by with a table full of the values from YEARWEEK:
201100
201101
201102
201103
201104
And here is a sketch of a sql statement:
SELECT year_weeks.yearweek , (SUM(`Duration`)/60/60)
FROM year_weeks LEFT OUTER JOIN logs_main
ON year_weeks.yearweek = logs_main.YEARWEEK(`Timestamp`)
WHERE `Stream`="asdf" GROUP BY year_weeks.yearweek;
Here is a suggestion. might not be exactly what you are looking for.
But say you had a simple table with one column [year_week] that contained the values of 1, 2, 3, 4... 52
You could then theoretically:
SELECT
A.year_week,
(SELECT SUM('Duration')/60/00) FROM logs_main WHERE
stream = 'asdf' AND YEARWEEK('TimeStamp') = A.year_week GROUP BY YEARWEEK('TimeStamp'))
FROM
tblYearWeeks A
this obviously needs some tweaking... i've done several similar queries in other projects and this works well enough depending on the situation.
If your looking for a one table/sql based solution then that is deffinately something I would be interested in as well!

Displaying same record twice- SQL Reporting Services

Ok, here's the situation: I need to display the same record in two different sections. stupid i know, but here's why.
The Report I am building is grouped by one Field, called Day. Each record has
date/times, an expected arrival date time, and an expected departure date/time.
so, at this point we have something like this:
Day..............Arrival Time..................Departure Time
18/5.............18/5 9.00am.........19/5 11.00am
The boss only wants to show times that relate to the current day in the arrive/depart coloumns (easy enough with expressions), which ends up like this:
Day..............Arrival Time..................Departure Time
18/5..............9.00am.........................-
the next thing he wants is to display the departing time in the correct day 'group', but as you can imagine as soon as you move to the next row, well you move to the next row of the table.
So the question is: is there anyway to display the same record on multiple coloumns? Have i missed something or have i got an unsolvable problem?
NOTE: this is not the only data in my table either. there is (for example) a name coloumn which also needs to be displayed on both days.
Cartesian Joins are great for duplicating data...
DECLARE #ArrDep TABLE
(
Code varchar(1)
)
INSERT INTO #ArrDep (Code) SELECT "A"
INSERT INTO #ArrDep (Code) SELECT "D"
SELECT DateAdd(dd, DateDiff(dd, 0,
CASE
WHEN ad.Code = "A"
THEN mt.ArrivalTime
ELSE mt.DepartureTime
END), 0) as TheDay
, *
FROM MyTable mt, #ArrDep ad
ORDER BY 1

Getting random and last value from group in SQL

I have a SQL table containing train schedules. The table looks something like this:
Schedule
TrainNumber
LegID
DepartureTime
DepartureStation
ArrivalTime
ArrivalStation
My real database contain several tables, but for this question only the one above is relevant. Different trainNumber can have different amount of legs. Based on a departure station chosen by a user, I want to output all upcoming routes from that station.
The output must contain Departure time and Arrival station. But I don't want to include the legs in between. Can anyone guide me in the right direction on how I can achieve this? I tried using a max statement. But didn't quite get it to work the way I wanted to.
Also, there can be multiple departures by the same train number on the same day.
You would need to use the combination (DepartureTime + TrainNumber) as the key to your query, get the maximum arrival time given that combination of values, and then find out what the corresponding ArrivalStation is. So you could do an inner join between the Schedule and a grouped version of itself, i.e.
SELECT
TrainTableA.TrainNumber
,TrainTableA.DepartureTime
,ArrivalStation
FROM
(SELECT /* all upcoming train routes for given station */
TrainNumber
,DepartureTime
,ArrivalTime
,ArrivalStation
FROM
Schedule
WHERE DepartureStation = givenStation
) as TrainTableA
INNER JOIN
(SELECT /* Just the last station for each departure */
TrainNumber
,DepartureTime
,Max(ArrivalTime) as a
FROM
Schedule
GROUP BY
TrainNumber
,DepartureTime
) as TrainTableB
ON
TrainTableA.TrainNumber = TrainTableB.TrainNumber
AND TrainTableA.DepartureTime = TrainTableB.DepartureTime
AND TrainTableA.ArrivalTime = TrainTableB.a
I can't quite tell from the question if you have a universal indicator of the route sequence, so I used max(ArrivalTime). You could also use max(LegID) if each LegID is greater than the one before it. Also, I assumed that The ArrivalTime includes the date, so 1:00 AM on the next day is still later than 10:00 PM on the same day. So, of course, adjust to taste.