Combine query results into a single row and display time span? - sql

First, I apologize for not having a fiddle, but my data set was too large. So I am including a file.
I have a set of queries that combine user data with location data. The location history data is gathered from RF devices and a history for that user is persisted. Going against the supplied SQL file I need to combine the data where a Staff member may enter a room, leave that room, then come back. This example may constitute a visit with a patient. Another example is if a Staff member is logged in a room consecutively. We are only concerned with data where the time stamps are greater than 2 minutes in length. Meaning the RF reader may read a tag if a staff member walks by a room and that location is logged. Here are the intial set of queries:
with
StaffHistory as(
SELECT
LocationHistories.UserProfileId,
UserProfiles.FirstName,
UserProfiles.LastName,
LocationHistories.LocationId,
Locations.LocationName,
LocationHistories.LocationHistoryTimeStamp,
PreviousLocationTime = LAG(LocationHistories.LocationHistoryTimeStamp, 1) OVER
(PARTITION BY LocationHistories.UserProfileId ORDER BY LocationHistories.LocationHistoryTimeStamp),
NextLocationTime = Lead(LocationHistories.LocationHistoryTimeStamp, 1) OVER
(PARTITION BY LocationHistories.UserProfileId ORDER BY LocationHistories.LocationHistoryTimeStamp)
FROM
LocationHistories
INNER JOIN UserProfiles ON LocationHistories.UserProfileId = UserProfiles.Id
INNER JOIN Locations ON LocationHistories.LocationId = Locations.Id
where LocationTrackingType = 1),
StaffInRoomTime as(
SELECT
StaffHistory.UserProfileId,
StaffHistory.FirstName,
StaffHistory.LastName,
StaffHistory.LocationId,
StaffHistory.LocationName,
DATEDIFF(SECOND, LocationHistoryTimeStamp, NextLocationTime) as TimeSpentInRoom,
StaffHistory.LocationHistoryTimeStamp,
StaffHistory.PreviousLocationTime,
StaffHistory.NextLocationTime
FROM
StaffHistory
Where DATEDIFF(SECOND, LocationHistoryTimeStamp, NextLocationTime) > 120
)
select * from StaffInRoomTime ORDER BY UserProfileId, LocationHistoryTimeStamp
I used common table expressions just for this example. These are actual views in the DB.
The first query joins the histories with the staff. We also create a couple columns for the Previous logged time and the Next logged time. This is so we can determine the length of time in a room.
The second query pulls from the first query and we set a column for how long the staff member was in that location during that time and we also filter any data out where the LocationHistoryTimeStamp and NextLocationTime are greater than 2 minutes.
What I am trying to achieve is combine the data where a staff member may be logged for a room consecutively or if they leave the room and come back.
Here is an example of the data set where the Staff member is in a room consecutively for:
Here would be the outcome:
Here is an example of spanning multiple rooms for a given visit:
I have tried using a Inner Join on the second query that uses the Min(LocationHistoryTimeStamp). However, the time spans ended up not being correct so I am missing something.
This was the Inner Join query I tried:
Select
StaffHistory.LocationId,
StaffHistory.LocationName,
StaffHistory.UserProfileId,
Min(LocationHistoryTimeStamp) as LocationHistoryTimeStamp,
DATEDIFF(SECOND, Min(LocationHistoryTimeStamp), Lead(Min(LocationHistoryTimeStamp), 1) OVER
(PARTITION BY UserProfileId ORDER BY Min(LocationHistoryTimeStamp))) As TimeSpentInRoom,
NextLocationTime = Lead(Min(LocationHistoryTimeStamp), 1) OVER
(PARTITION BY UserProfileId ORDER BY Min(LocationHistoryTimeStamp))
FROM
StaffHistory
Where TimeSpentInRoom > 120
GROUP BY LocationId,LocationName,UserProfileId

Here is statement:
WITH StaffHistory
AS ( SELECT LocationHistories.UserProfileId ,
UserProfiles.FirstName ,
UserProfiles.LastName ,
LocationHistories.LocationId ,
Locations.LocationName ,
LocationHistories.LocationHistoryTimeStamp ,
PreviousLocationTime = LAG(LocationHistories.LocationHistoryTimeStamp,
1) OVER ( PARTITION BY LocationHistories.UserProfileId ORDER BY LocationHistories.LocationHistoryTimeStamp ) ,
NextLocationTime = LEAD(LocationHistories.LocationHistoryTimeStamp,
1) OVER ( PARTITION BY LocationHistories.UserProfileId ORDER BY LocationHistories.LocationHistoryTimeStamp )
FROM LocationHistories
INNER JOIN UserProfiles ON LocationHistories.UserProfileId = UserProfiles.Id
INNER JOIN Locations ON LocationHistories.LocationId = Locations.Id
WHERE LocationTrackingType = 1
),
StaffInRoomTime
AS ( SELECT StaffHistory.UserProfileId ,
StaffHistory.FirstName ,
StaffHistory.LastName ,
StaffHistory.LocationId ,
StaffHistory.LocationName ,
DATEDIFF(SECOND, LocationHistoryTimeStamp,
NextLocationTime) AS TimeSpentInRoom ,
StaffHistory.LocationHistoryTimeStamp ,
StaffHistory.PreviousLocationTime ,
StaffHistory.NextLocationTime
FROM StaffHistory
WHERE DATEDIFF(SECOND, LocationHistoryTimeStamp,
NextLocationTime) > 120
),
prepareIsland
AS ( SELECT * ,
CASE WHEN LAG(LocationId) OVER ( PARTITION BY UserProfileId ORDER BY LocationHistoryTimeStamp ) <> LocationId
THEN 1
ELSE 0
END AS prepIsland
FROM StaffInRoomTime
),
islands
AS ( SELECT * ,
SUM(prepIsland) OVER ( ORDER BY UserProfileId , LocationHistoryTimeStamp ) AS Island
FROM prepareIsland
)
SELECT island ,
UserProfileId ,
FirstName ,
LastName ,
LocationId ,
LocationName ,
SUM(TimeSpentInRoom) TimeSpentInRoom ,
MIN(LocationHistoryTimeStamp) LocationHistoryTimeStamp ,
MIN(PreviousLocationTime) PreviousLocationTime ,
MAX(NextLocationTime) NextLocationTime
FROM islands
GROUP BY island ,
UserProfileId ,
FirstName ,
LastName ,
LocationId ,
LocationName
ORDER BY UserProfileId ,
LocationHistoryTimeStamp

Related

Query keeps giving me duplicate records. How can I fix this?

I wrote a query which uses 2 temp tables. And then joins them into 1. However, I am seeing duplicate records in the student visit temp table. (Query is below). How could this be modified to remove the duplicate records of the visit temp table?
with clientbridge as (Select *
from (Select visitorid, --Visid
roomnumber,
room_id,
profid,
student_id,
ambc.datekey,
RANK() over(PARTITION BY visitorid,student_id,profid ORDER BY ambc.datekey desc) as rn
from university.course_office_hour_bridge cohd
--where student_id = '9999999-aaaa-6634-bbbb-96fa18a9046e'
)
where rn = 1 --visitorid = '999999999999999999999999999999'---'1111111111111111111111111111111' --and pai.datekey is not null --- 00000000000000000000000000
),
-----------------Data Header Table
studentvisit as
(SELECT
--Visit key will allow us to track everything they did within that visit.
distinct visid_visitorid,
--calcualted_visitorid,
uniquevisitkey,
--channel, -- says the room they're in. Channel might not be reliable would need to see how that operates
--office_list, -- add 7 to exact
--user_college,
--first_office_hour_name,
--first_question_time_attended,
studentaccountid_5,
profid_officenumber_8,
studentvisitstarttime,
room_id_115,
--date_time,
qqq144, --Course Name
qqq145, -- Course Office Hour Benefit
qqq146, --Course Office Hour ID
datekey
FROM university.office_hour_details ohd
--left_join niversity.course_office_hour_bridge cohd on ohd.visid_visitorid
where DateKey >='2022-10-01' --between '2022-10-01' and '2022-10-27'
and (qqq146 <> '')
)
select
*
from clientbridge ab inner join studentvisit sv on sv.visid_visitorid = cb.visitorid
I wrote a query which uses 2 temp tables. And then joins them into 1. However, I am seeing duplicate records in the student visit temp table. (Query is below). How could this be modified to remove the duplicate records of the visit temp table?
I think you may get have a better shot by joining the two datasets in the same query where you want the data ranked, otherwise your rank from query will be ignored within the results from the second query. Perhaps, something like ->
;with studentvisit as
(SELECT
--Visit key will allow us to track everything they did within that visit.
distinct visid_visitorid,
--calcualted_visitorid,
uniquevisitkey,
--channel, -- says the room they're in. Channel might not be reliable would need to see how that operates
--office_list, -- add 7 to exact
--user_college,
--first_office_hour_name,
--first_question_time_attended,
studentaccountid_5,
profid_officenumber_8,
studentvisitstarttime,
room_id_115,
--date_time,
qqq144, --Course Name
qqq145, -- Course Office Hour Benefit
qqq146, --Course Office Hour ID
datekey
FROM university.office_hour_details ohd
--left_join niversity.course_office_hour_bridge cohd on ohd.visid_visitorid
where DateKey >='2022-10-01' --between '2022-10-01' and '2022-10-27'
and (qqq146 <> '')
)
,clientbridge as (
Select
sv.*,
university.course_office_hour_bridge cohd, --Visid
roomnumber,
room_id,
profid,
student_id,
ambc.datekey,
RANK() over(PARTITION BY sv.visitorid,sv.student_id,sv,profid ORDER BY ambc.datekey desc) as rn
from university.course_office_hour_bridge cohd
inner join studentvisit sv on sv.visid_visitorid = cohd.visitorid
)
select
*
from clientbridge WHERE rn=1

For some reason it says a table is not found? - it says the student visit is not found when i start the client bridge query

I wrote a query which uses 2 temp tables. And then joins them into 1. However, I am seeing duplicate records in the student visit temp table. (Query is below). How could this be modified to remove the duplicate records of the visit temp table?
with studentvisit as
(SELECT
--Visit key will allow us to track everything they did within that visit.
distinct visid_visitorid,
uniquevisitkey,
studentaccountid_5,
profid_officenumber_8,
studentvisitstarttime,
room_id_115,
qqq144, --Rewards Accrual Name
qqq145, -- Rewards accrual type what they earned
qqq146, --Rewards Accrual ID
datekey
FROM university.office_hour_details ohd
where DateKey >='2022-10-27' --between '2022-10-26' and '2022-10-27'
and (qqq146 <> '')
)
,clientbridge as (
Select
studentvisit.*, university.course_office_hour_bridge cohd,
cohd.visitorid,
cohd.roomnumber,
cohd.room_id,
cohd.profid,
cohd.student_id,
cohd.datekey,
RANK() over(PARTITION BY adobevisitorid,student_id,profid ORDER BY cohd.datekey desc) as rn
from university.course_office_hour_bridge cohd
inner join studentvisit sv on sv.visid_visitorid = cohd.adobevisitorid
)
select * from clientbridge WHERE rn = 1

Pivot rows to columns

I need to create one master table to present in reporting services, but i have an issue on how to combine the data.
To be more specific, i have one table named "Reservaciones" which store information from residences that have been reserved in certain dates.
Now for example, I´m grouping the information by this fields:
R.ClaTrab AS WorkerId
R.ClaUbicacion AS UbicationID
R.ClaEstancia AS ResidenceID
R.FechaIni AS InitialDay
R.FechaFin AS LastDay
And the result is First result**
As you see in the picture we have two rows duplicated, the number four and number five to be exact.
So far this is my code
SELECT
R.ClaTrab AS WorkerId,
MAX(E.NomEstancia) AS ResidenceName,
R.ClaUbicacion AS UbicationID,
R.ClaEstancia AS ResidenceID,
DATEDIFF(DAY, R.FechaIni, R.FechaFin) AS NumberDays,
R.FechaIni AS InitialDay,
R.FechaFin AS LastDay
FROM Reservaciones AS R
INNER JOIN Estancias AS E ON E.ClaEstancia = R.ClaEstancia
WHERE E.ClaUbicacionEst = 3
GROUP BY R.ClaTrab,R.ClaUbicacion, R.ClaEstancia, R.FechaIni, R.FechaFin
ORDER BY R.FechaIni
I Want the result to be like this desire result, but i dont know how to do it, i have tried PIVOT but i cant get the result i want it.
If u need more information please, ask me.
thank you very much.
SOLUTION:
What i did is use the ROW NUMBER() and OVER PARTITION BY to create a group of workers in the same residence, then PIVOT the result in new columns.
SNIPPET
SELECT * FROM(
SELECT
MAX(E.NomEstancia) AS ResidenceName,
R.FechaIni AS InitialDay,
R.FechaFin AS LastDay,
DATEDIFF(DAY, R.FechaIni, R.FechaFin) AS NumberDays,
T.NomTrab AS Worker,
R.ClaUbicacion AS UbicationID,
R.ClaEstancia AS ResidenceID,
ROW_NUMBER() OVER(PARTITION BY FechaIni,FechaFin, R.ClaUbicacion, R.ClaEstancia ORDER BY T.NomTrab) AS GUEST
FROM Reservaciones AS R
INNER JOIN Estancias AS E ON E.ClaEstancia = R.ClaEstancia
INNER JOIN Trabajadores AS T ON T.ClaTrab = R.ClaTrab
WHERE E.ClaUbicacionEst = 3
GROUP BY T.NomTrab, R.ClaUbicacion, R.ClaEstancia, R.FechaIni,R.FechaFin) AS ONE
PIVOT( MAX(Worker) FOR GUEST IN ([1],[2],[3])) AS pvt
In the new query I added a new join to obtain the name of the workers
Since there can only be 2 workers, you can use Min and Max.
with cte as(
SELECT
R.ClaTrab AS WorkerId,
MAX(E.NomEstancia) AS ResidenceName,
R.ClaUbicacion AS UbicationID,
R.ClaEstancia AS ResidenceID,
DATEDIFF(DAY, R.FechaIni, R.FechaFin) AS NumberDays,
R.FechaIni AS InitialDay,
R.FechaFin AS LastDay
FROM
Reservaciones AS R
INNER JOIN
Estancias AS E
ON E.ClaEstancia = R.ClaEstancia
WHERE
E.ClaUbicacionEst = 3
GROUP BY
R.ClaTrab,
R.ClaUbicacion,
R.ClaEstancia,
R.FechaIni,
R.FechaFin),
cte2 as(
select
ResidenceName
,UbicationID
,ResidenceID
,NumberDays
,InitalDay
,LastDay
,Worker1 = max(WorkerId)
,Worker2 = min(WorkerId)
from
cte
group by
ResidenceName
,UbicationID
,ResidenceID
,NumberDays
,InitalDay
,LastDay)
select
ResidenceName
,UbicationID
,ResidenceID
,NumberDays
,InitalDay
,LastDay
,Worker1
,Worker2 = case when Worker1 = Worker2 then NULL else Worker2 end
from
cte2
ONLINE DEMO WITH PARTIAL TEST DATA

Find Segment with Longest Stay Per Booking

We have a number of bookings and one of the requirements is that we display the Final Destination for a booking based on its segments. Our business has defined the Final Destination as that in which we have the longest stay. And Origin being the first departure point.
Please note this is not the segments with the Longest Travel time i.e. Datediff(minute, DepartDate, ArrivalDate) This is requesting the one with the Longest gap between segments.
This is a simplified version of the tables:
Create Table Segments
(
BookingID int,
SegNum int,
DepartureCity varchar(100),
DepartDate datetime,
ArrivalCity varchar(100),
ArrivalDate datetime
);
Create Table Bookings
(
BookingID int identity(1,1),
Locator varchar(10)
);
Insert into Segments values (1,2,'BRU','2010-03-06 10:40','FIH','2010-03-06 20:20:00')
Insert into Segments values (1,4,'FIH','2010-03-13 21:50:00','BRU', '2010-03-14 07:25:00')
Insert into Segments values (2,2,'BOD','2010-02-10 06:50:00','AMS','2010-02-10 08:50:00')
Insert into Segments values (2,3,'AMS','2010-02-10 10:40:00','EBB','2010-02-10 20:40:00')
Insert into Segments values (2,4,'EBB','2010-02-28 22:55:00','AMS','2010-03-01 05:35:00')
Insert into Segments values (2,5,'AMS','2010-03-01 10:25:00','BOD','2010-03-01 12:15:00')
insert into Segments values (3,2,'BRU','2010-03-09 12:10:00','IAD','2010-03-09 14:46:00')
Insert into Segments Values (3,3,'IAD','2010-03-13 17:57:00','BRU','2010-03-14 07:15:00')
insert into segments values (4,2,'BRU','2010-07-27','ADD','2010-07-28')
insert into segments values (4,4,'ADD','2010-07-28','LUN','2010-07-28')
insert into segments values (4,5,'LUN','2010-08-23','ADD','2010-08-23')
insert into segments values (4,6,'ADD','2010-08-23','BRU','2010-08-24')
Insert into Bookings values('5MVL7J')
Insert into Bookings values ('Y2IMXQ')
insert into bookings values ('YCBL5C')
Insert into bookings values ('X7THJ6')
I have created a SQL Fiddle with real data here:
SQL Fiddle Example
I have tried to do the following, however this doesn't appear to be correct.
SELECT Locator, fd.*
FROM Bookings ob
OUTER APPLY
(
SELECT Top 1 DepartureCity, ArrivalCity
from
(
SELECT DISTINCT
seg.segnum ,
seg.DepartureCity ,
seg.DepartDate ,
seg.ArrivalCity ,
seg.ArrivalDate,
(SELECT
DISTINCT
DATEDIFF(MINUTE , seg.ArrivalDate , s2.DepartDate)
FROM Segments s2
WHERE s2.BookingID = seg.BookingID AND s2.segnum = seg.segnum + 1) 'LengthOfStay'
FROM Bookings b(NOLOCK)
INNER JOIN Segments seg (NOLOCK) ON seg.bookingid = b.bookingid
WHERE b.Locator = ob.locator
) a
Order by a.lengthofstay desc
)
FD
The results I expect are:
Locator Origin Destination
5MVL7J BRU FIH
Y2IMXQ BOD EBB
YCBL5C BRU IAD
X7THJ6 BRU LUN
I get the feeling that a CTE would be the best approach, however my attempts do this so far failed miserably. Any help would be greatly appreciated.
I have managed to get the following query working but it only works for one at a time due to the top one, but I'm not sure how to tweak it:
WITH CTE AS
(
SELECT distinct s.DepartureCity, s.DepartDate, s.ArrivalCity, s.ArrivalDate, b.Locator , ROW_NUMBER() OVER (PARTITION BY b.Locator ORDER BY SegNum ASC) RN
FROM Segments s
JOIN bookings b ON s.bookingid = b.BookingID
)
SELECT C.Locator, c.DepartureCity, a.ArrivalCity
FROM
(
SELECT TOP 1 C.Locator, c.ArrivalCity, c1.DepartureCity, DATEDIFF(MINUTE,c.ArrivalDate, c1.DepartDate) 'ddiff'
FROM CTE c
JOIN cte c1 ON c1.Locator = C.Locator AND c1.rn = c.rn + 1
ORDER BY ddiff DESC
) a
JOIN CTE c ON C.Locator = a.Locator
WHERE c.rn = 1
You can try something like this:
;WITH CTE_Start AS
(
--Ordering of segments to eliminate gaps
SELECT *, ROW_NUMBER() OVER (PARTITION BY BookingID ORDER BY SegNum) RN
FROM dbo.Segments
)
, RCTE_Stay AS
(
--recursive CTE to calculate stay between segments
SELECT *, 0 AS Stay FROM CTE_Start s WHERE RN = 1
UNION ALL
SELECT sNext.*, DATEDIFF(Mi, s.ArrivalDate, sNext.DepartDate)
FROM CTE_Start sNext
INNER JOIN RCTE_Stay s ON s.RN + 1 = sNext.RN AND s.BookingID = sNext.BookingID
)
, CTE_Final AS
(
--Search for max(stay) for each bookingID
SELECT *, ROW_NUMBER() OVER (PARTITION BY BookingID ORDER BY Stay DESC) AS RN_Stay
FROM RCTE_Stay
)
--join Start and Final on RN=1 to find origin and departure
SELECT b.Locator, s.DepartureCity AS Origin, f.DepartureCity AS Destination
FROM CTE_Final f
INNER JOIN CTE_Start s ON f.BookingID = s.BookingID
INNER JOIN dbo.Bookings b ON b.BookingID = f.BookingID
WHERE s.RN = 1 AND f.RN_Stay = 1
SQLFiddle DEMO
You can use the OUTER APPLY + TOP operators to find the next values SegNum. After finding the gap between segments are used MIN/MAX aggregate functions with OVER clause as conditions in the CASE expression
;WITH cte AS
(
SELECT seg.BookingID,
CASE WHEN MIN(seg.segNum) OVER(PARTITION BY seg.BookingID) = seg.segNum
THEN seg.DepartureCity END AS Origin,
CASE WHEN MAX(DATEDIFF(MINUTE, seg.ArrivalDate, o.DepartDate)) OVER(PARTITION BY seg.BookingID)
= DATEDIFF(MINUTE, seg.ArrivalDate, o.DepartDate)
THEN o.DepartureCity END AS Destination
FROM Segments seg (NOLOCK)
OUTER APPLY (
SELECT TOP 1 seg2.DepartDate, seg2.DepartureCity
FROM Segments seg2
WHERE seg.BookingID = seg2.BookingID
AND seg.SegNum < seg2.SegNum
ORDER BY seg2.SegNum ASC
) o
)
SELECT b.Locator, MAX(c.Origin) AS Origin, MAX(c.Destination) AS Destination
FROM cte c JOIN Bookings b ON c.BookingID = b.BookingID
GROUP BY b.Locator
See demo on SQLFiddle
The statement below:
;WITH DataSource AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY BookingID ORDER BY DATEDIFF(SS,DepartDate,ArrivalDate) DESC) AS Row
,Segments.BookingID
,Segments.SegNum
,Segments.DepartureCity
,Segments.DepartDate
,Segments.ArrivalCity
,Segments.ArrivalDate
,DATEDIFF(SS,DepartDate,ArrivalDate) AS DiffInSeconds
FROM Segments
)
SELECT *
FROM DataSource DS
INNER JOIN Bookings B
ON DS.[BookingID] = B.[BookingID]
Will give the following output:
So, adding the following clause to the above statement:
WHERE Row = 1
will give you what you need.
Few important things:
As you can see from the screenshot below, there are two records with same difference in second. If you want to show both of them (or all of them if there are), instead ROW_NUMBER function use RANK function.
The return type of DATEDIFF is INT. So, there is limitation for seconds max deference value. It is as follows:
If the return value is out of range for int (-2,147,483,648 to
+2,147,483,647), an error is returned. For millisecond, the maximum difference between startdate and enddate is 24 days, 20 hours, 31
minutes and 23.647 seconds. For second, the maximum difference is 68
years.

SQL query ...multiple max value selection. Help needed

Business World 1256987 monthly 10 2009-10-28
Business World 1256987 monthly 10 2009-09-23
Business World 1256987 monthly 10 2009-08-18
Linux 4 U 456734 monthly 25 2009-12-24
Linux 4 U 456734 monthly 25 2009-11-11
Linux 4 U 456734 monthly 25 2009-10-28
I get this result with the query:
SELECT DISTINCT ljm.journelname,ljm. subscription_id,
ljm.frequency,ljm.publisher, ljm.price, ljd.receipt_date
FROM lib_journals_master ljm,
lib_subscriptionhistory
lsh,lib_journal_details ljd
WHERE ljd.journal_id=ljm.id
ORDER BY ljm.publisher
What I need is the latest date in each journal?
I tried this query:
SELECT DISTINCT ljm.journelname, ljm.subscription_id,
ljm.frequency, ljm.publisher, ljm.price,ljd.receipt_date
FROM lib_journals_master ljm,
lib_subscriptionhistory lsh,
lib_journal_details ljd
WHERE ljd.journal_id=ljm.id
AND ljd.receipt_date = (
SELECT max(ljd.receipt_date)
from lib_journal_details ljd)
But it gives me the maximum from the entire column. My needed result will have two dates (maximum of each magazine), but this query gives me only one?
You could change the WHERE statement to look up the last date for each journal:
AND ljd.receipt_date = (
SELECT max(subljd.receipt_date)
from lib_journal_details subljd
where subljd.journelname = ljd.journelname)
Make sure to give the table in the subquery a different alias from the table in the main query.
You should use Group By if you need the Max from date.
Should look something like this:
SELECT
ljm.journelname
, ljm.subscription_id
, ljm.frequency
, ljm.publisher
, ljm.price
, **MAX(ljd.receipt_date)**
FROM
lib_journals_master ljm
, lib_subscriptionhistory lsh
, lib_journal_details ljd
WHERE
ljd.journal_id=ljm.id
GROUP BY
ljm.journelname
, ljm.subscription_id
, ljm.frequency
, ljm.publisher
, ljm.price
Something like this should work for you.
SELECT ljm.journelname
, ljm.subscription_id
, ljm.frequency
, ljm.publisher
, ljm.price
,md.max_receipt_date
FROM lib_journals_master ljm
, ( SELECT journal_id
, max(receipt_date) as max_receipt_date
FROM lib_journal_details
GROUP BY journal_id) md
WHERE ljm.id = md.journal_id
/
Note that I have removed the tables from the FROM clause which don't contribute anything to the query. You may need to replace them if yopu simplified your scenario for our benefit.
Separate this into two queries one will get journal name and latest date
declare table #table (journalName as varchar,saleDate as datetime)
insert into #table
select journalName,max(saleDate) from JournalTable group by journalName
select all fields you need from your table and join #table with them. join on journalName.
Sounds like top of group. You can use a CTE in SQL Server:
;WITH journeldata AS
(
SELECT
ljm.journelname
,ljm.subscription_id
,ljm.frequency
,ljm.publisher
,ljm.price
,ljd.receipt_date
,ROW_NUMBER() OVER (PARTITION BY ljm.journelname ORDER BY ljd.receipt_date DESC) AS RowNumber
FROM
lib_journals_master ljm
,lib_subscriptionhistory lsh
,lib_journal_details ljd
WHERE
ljd.journal_id=ljm.id
AND ljm.subscription_id = ljm.subscription_id
)
SELECT
journelname
,subscription_id
,frequency
,publisher
,price
,receipt_date
FROM journeldata
WHERE RowNumber = 1