Display of online users on the system - sql-server

I don't know exactly where I'm wrong, but I need a list of all the workers who are currently at work (for the current day), this is my sql query:
SELECT
zp.ID,
zp.USER_ID,
zp.Arrive,
zp.Deppart,
zp.DATUM
FROM time_recording as zp
INNER JOIN personal AS a on zp.USER_ID, = zp.USER_ID,
WHERE zp.Arrive IS NOT NULL
AND zp.Deppart IS NULL
AND zp.DATUM = convert(date, getdate())
ORDER BY zp.ID DESC
this is what the data looks like with my query:
For me the question is, how can I correct my query so that I only get the last Arrive time for the current day for each user?
In this case to get only these values:

Try this below script using ROW_NUMBER as below-
SELECT * FROM
(
SELECT zp.ID, zp.USER_ID, zp.Arrive, zp.Deppart, zp.DATUM,
ROW_NMBER() OVER(PARTITION BY zp.User_id ORDER BY zp.Arrive DESC) RN
FROM time_recording as zp
INNER JOIN personal AS a
on zp.USER_ID = zp.USER_ID
-- You need to adjust above join relation as both goes to same table
-- In addition, as you are selecting nothing from table personal, you can drop the total JOIN part
WHERE zp.Arrive IS NOT NULL
AND zp.Deppart IS NULL
AND zp.DATUM = convert(date, getdate())
)A
WHERE RN =1

you can try this:
SELECT DISTINCT
USER_ID,
LAR.LastArrive
FROM time_recording as tr
CROSS APPLY (
SELECT
MAX(Arrive) as LastArrive
FROM time_recording as ta
WHERE
tr.USER_ID = ta.USER_ID AND
ta.Arrive IS NOT NULL
) as LAR

Related

Returning a single date with max(date)

I have the following query. I want to retrieve a list of unique Object ID's with the value closest to a specified date:
INSERT INTO #temp
(
[Object ID]
,[Waarde]
,[Kenmerk]
)
select DISTINCT PME.OBJECTID,
LEFT(PME.OBJECTSCORINGVALUE,LEN(PME.OBJECTSCORINGVALUE)-2),
'P3'
FROM PMEOBJECTSCORINGPOINTS PME
LEFT JOIN PMEOBJECTSCORINGHISTORY PMEH ON PME.OBJECTSCORINGHISTORYID = PMEH.OBJECTSCORINGHISTORYID
INNER JOIN(SELECT OBJECTSCORINGHISTORYID, MAX(DATE) DATE
FROM PMEOBJECTSCORINGHISTORY
WHERE DATE < DATEFROMPARTS(YEAR(getdate())-1, 12, 31)
GROUP BY OBJECTSCORINGHISTORYID) P3 ON PME.OBJECTSCORINGHISTORYID = P3.OBJECTSCORINGHISTORYID
AND PMEH.DATE = P3.DATE
AND PME.ATTRIBUTEID = 'Energie-idx'
AND PME.OBJECTSCORINGVALUE <> ''
------------------
select * from #temp
order by [Object ID], [Kenmerk] ASC
When a certain Object ID only has one known value before 2019-12-31, I get one record in the result set. However, if an Object ID has two (or more) known values before that date, I still get multiple results instead of the value for the date closest to 2019-12-31.
Any pointers on how to get the desired results? Thanks in advance!
(edit: apologies for the bad readibility on the code, thanks for fixing it)
Use analytical funtion ROW_NUMBER(), if you can sort on a column, Perhaps P3.Date or PME.OBJECTSCORINGVALUE
select Objectid, OBJECTSCORINGVALUE,P3
from(
select PME.OBJECTID,
LEFT(PME.OBJECTSCORINGVALUE,LEN(PME.OBJECTSCORINGVALUE)-2) OBJECTSCORINGVALUE,
'P3' Pcol,P3.Date
row_number() over (partition by PME.OBJECTID, LEFT(PME.OBJECTSCORINGVALUE,LEN(PME.OBJECTSCORINGVALUE)-2) order by P3.Date DESC) rn
FROM PMEOBJECTSCORINGPOINTS PME
LEFT JOIN PMEOBJECTSCORINGHISTORY PMEH ON PME.OBJECTSCORINGHISTORYID = PMEH.OBJECTSCORINGHISTORYID
INNER JOIN(SELECT OBJECTSCORINGHISTORYID, MAX(DATE) DATE
FROM PMEOBJECTSCORINGHISTORY
WHERE DATE < DATEFROMPARTS(YEAR(getdate())-1, 12, 31)
GROUP BY OBJECTSCORINGHISTORYID) P3 ON PME.OBJECTSCORINGHISTORYID = P3.OBJECTSCORINGHISTORYID
AND PMEH.DATE = P3.DATE
AND PME.ATTRIBUTEID = 'Energie-idx'
AND PME.OBJECTSCORINGVALUE <> ''
) where rn=1
Here I order the replies with P3.Date, and return only the one with the highest value.
It is guaranteed to only return one row, however you have to be sure about your data to be sure that it is deterministic
I fixed the problem. Turned out I did an incorrect join (wrong level of granularity). I should have done it on OBJECTID instead of OBJECTSCORINGHISTORYID. The result was that the max(date) was returned for OBJECTSCORINGHISTORYID instead of on the level of OBJECTID.
This is the correct query:
INSERT INTO #temp
(
[Object ID]
,[Waarde]
,[Kenmerk]
)
select PME.OBJECTID,
LEFT(PME.OBJECTSCORINGVALUE,LEN(PME.OBJECTSCORINGVALUE)-2),
'P3'
FROM PMEOBJECTSCORINGPOINTS PME
LEFT JOIN PMEOBJECTSCORINGHISTORY PMEH ON PME.OBJECTSCORINGHISTORYID = PMEH.OBJECTSCORINGHISTORYID
INNER JOIN(SELECT OBJECTID, MAX(DATE) DATE
FROM PMEOBJECTSCORINGHISTORY
WHERE DATE < DATEFROMPARTS(YEAR(getdate())-1, 12, 31)
GROUP BY OBJECTID) P3 ON PME.OBJECTID = P3.OBJECTID
AND PMEH.DATE = P3.DATE
AND PME.ATTRIBUTEID = 'Energie-idx'
AND PME.OBJECTSCORINGVALUE <> ''

SQL Query Get Last record Group by multiple fields

Hi I have a table with following fields:
ALERTID POLY_CODE ALERT_DATETIME ALERT_TYPE
I need to query above table for records in the last 24 hour.
Then group by POLY_CODE and ALERT_TYPE and get the latest Alert_Level value ordered by ALERT_DATETIME
I can get up to this, but I need the AlertID of the resulting records.
Any suggestions what would be an efficient way of getting this ?
I have created an SQL in SQL Server. See below
SELECT POLY_CODE, ALERT_TYPE, X.ALERT_LEVEL AS LAST_ALERT_LEVEL
FROM
(SELECT * FROM TableA where ALERT_DATETIME >= GETDATE() -1) T1
OUTER APPLY (SELECT TOP 1 [ALERT_LEVEL]
FROM (SELECT * FROM TableA where ALERT_DATETIME >= GETDATE() -1) T2
WHERE T2.POLY_CODE = T1.POLY_CODE AND
T2.ALERT_TYPE = T1.ALERT_TYPE ORDER BY T2.[ALERT_DATETIME] DESC) X
GROUP BY POLY_CODE, ALERT_TYPE, X.[ALERT_LEVEL]
POLY_CODE ALERT_TYPE ALERT_LEVEL
04575 Elec 2
04737 Gas 3
06239 Elec 2
06552 Elec 2
06578 Elec 2
10320 Elec 2
select top 1 with ties *
from TableA
where ALERT_DATETIME >= GETDATE() -1
order by row_number() over (partition by POLY_CODE,ALERT_TYPE order by [ALERT_DATETIME] DESC)
The way this works is that for each group of POLY_CODE,ALERT_TYPE get their own row_number() starting from the most recent alert_datetime. Then, the with ties clause ensures that all rows(= all groups) with the row_number value of 1 get returned.
One way of doing it is creating a cte with the grouping that calculates the latesdatetime for each and then crosses it with the table to get the results. Just keep in mind that if there are more than one record with the same combination of poly_code, alert_type, alert_level and datetime they will all show.
WITH list AS (
SELECT ta.poly_code,ta.alert_type,MAX(ta.alert_datetime) AS LatestDatetime,
ta.alert_level
FROM dbo.TableA AS ta
WHERE ta.alert_datetime >= DATEADD(DAY,-1,GETDATE())
GROUP BY ta.poly_code, ta.alert_type,ta.alert_level
)
SELECT ta.*
FROM list AS l
INNER JOIN dbo.TableA AS ta ON ta.alert_level = l.alert_level AND ta.alert_type = l.alert_type AND ta.poly_code = l.poly_code AND ta.alert_datetime = l.LatestDatetime

Clean up SQL Server script

SELECT pp.pat_key, MAX(pp.PROV_NPI) [Provider_ID], CONCAT(pp.LAST_NM,' ',pp.FIRST_NM) [Provider_Name]
INTO pat_primary_provider
FROM TRDW.dbo.PATIENT_PROVIDER pp
WHERE IS_PCP=1
AND pat_key IN (SELECT Consumer_ID FROM CareWire0521)
GROUP BY pp.PAT_KEY, pp.last_nm, pp.FIRST_NM;
SELECT ppp.*
INTO ppp1
FROM (SELECT PAT_KEY, MAX(provider_ID) AS maxprov FROM pat_primary_provider GROUP BY PAT_KEY) AS x
INNER JOIN pat_primary_provider AS ppp ON ppp.PAT_KEY = x.PAT_KEY AND ppp.Provider_ID = x.maxprov;
I need to get the results of ppp1 only using one query (no INTO statements) in SQL Server. Please help.
Simply put the first query into a CTE (without the INTO clause). Then select from that.
;WITH pat_primary_provider AS
(
-- The first query goes here
)
-- The second query goes here
But something like below might also return the PAT_KEY's with the maximum PROV_NPI:
SELECT TOP 1 WITH TIES
PAT_KEY,
MAX(PROV_NPI) AS [Max_Provider_ID],
CONCAT(LAST_NM,' ',FIRST_NM) AS [Patient_Provider_Full_Name]
FROM TRDW.dbo.PATIENT_PROVIDER pp
WHERE IS_PCP = 1
AND PAT_KEY IN (SELECT Consumer_ID FROM CareWire0521)
GROUP BY PAT_KEY, LAST_NM, FIRST_NM
ORDER BY row_number() over (order by MAX(PROV_NPI) desc);
Whats wrong with just inserting the first query as subqueries into the second?
SELECT ppp.*
FROM (SELECT PAT_KEY, MAX(provider_ID) AS maxprov FROM (SELECT pp.pat_key, MAX(pp.PROV_NPI) [Provider_ID], CONCAT(pp.LAST_NM,' ',pp.FIRST_NM) [Provider_Name]
FROM TRDW.dbo.PATIENT_PROVIDER pp
WHERE IS_PCP=1
AND pat_key IN (SELECT Consumer_ID FROM CareWire0521)
GROUP BY pp.PAT_KEY, pp.last_nm, pp.FIRST_NM) GROUP BY PAT_KEY) AS x
INNER JOIN (SELECT pp.pat_key, MAX(pp.PROV_NPI) [Provider_ID], CONCAT(pp.LAST_NM,' ',pp.FIRST_NM) [Provider_Name]
FROM TRDW.dbo.PATIENT_PROVIDER pp
WHERE IS_PCP=1
AND pat_key IN (SELECT Consumer_ID FROM CareWire0521)
GROUP BY pp.PAT_KEY, pp.last_nm, pp.FIRST_NM) AS ppp ON ppp.PAT_KEY = x.PAT_KEY AND ppp.Provider_ID = x.maxprov;

Using the results of WITH clause IN where STATEMENT of main query

I am relatively new at SQL so I apologise if this is obvious but I cannot work out how to use the results of the WITH clause query in the where statement of my main query.
My with query pulls the first record for each customer and gives the sale date for that record:
WITH summary AS(
SELECT ed2.customer,ed2.saledate,
ROW_NUMBER()OVER(PARTITION BY ed2.customer
ORDER BY ed2.saledate)AS rk
FROM Filteredxportdocument ed2)
SELECT s.*
FROM summary s
WHERE s.rk=1
I need to use the date in the above query as the starting point and pull all records for each customer for their first 12 months i.e. where the sale date is between ed2.saledate AND ed2.saledate+12 months.
My main query is:
SELECT ed.totalamountincvat, ed.saledate, ed.name AS SaleRef,
ed.customer, ed.customername, comp.numberofemployees,
comp.companyuid
FROM exportdocument AS ed INNER JOIN
FilteredAccount AS comp ON ed.customer = comp.accountid
WHERE (ed.statecode = 0) AND
ed.saledate BETWEEN ed2.saledate AND DATEADD(M,12,ed2.saledate)
I am sure that I need to add the main query into the WITH clause but I cant work out where. Is anyone able to help please
Does this help?
;WITH summary AS(
SELECT ed2.customer,ed2.saledate,
ROW_NUMBER()OVER(PARTITION BY ed2.customer
ORDER BY ed2.saledate)AS rk
FROM Filteredxportdocument ed2)
SELECT ed.totalamountincvat, ed.saledate, ed.name AS SaleRef,
ed.customer, ed.customername, comp.numberofemployees,
comp.companyuid
FROM exportdocument AS ed INNER JOIN
FilteredAccount AS comp ON ed.customer = comp.accountid
OUTER APPLY (SELECT s.* FROM summary s WHERE s.rk=1) ed2
WHERE ed.statecode = 0 AND
ed.saledate BETWEEN ed2.saledate AND DATEADD(M,12,ed2.saledate)
and ed.Customer = ed2.Customer
Results of CTE are not cached or stored, so you can't reuse it.
EDIT:
Based upon your requirement that all the records from CTE should be in final result, this is a new query:
;WITH summary AS(
SELECT ed2.customer,ed2.saledate,
ROW_NUMBER()OVER(PARTITION BY ed2.customer
ORDER BY ed2.saledate)AS rk
FROM Filteredxportdocument ed2)
SELECT
ed.totalamountincvat,
ed.saledate,
ed.name AS SaleRef,
ed.customer,
ed.customername,
comp.numberofemployees,
comp.companyuid
FROM
summary ed2
left join exportdocument ed
on ed.Customer = ed2.Customer
and ed.statecode = 0
AND ed.saledate BETWEEN ed2.saledate AND DATEADD(M,12,ed2.saledate)
INNER JOIN FilteredAccount comp
ON ed.customer = comp.accountid
WHERE
s.rk=1
summary you will be able to use only once. Alternate solution is store summary into temp table and use that as many times as u want.
Something like : Select * into #temp from Summary s where s.rk=1

Join subquery with min

I'm pulling my hair out over a subquery that I'm using to avoid about 100 duplicates (out of about 40k records). The records that are duplicated are showing up because they have 2 dates in h2.datecreated for a valid reason, so I can't just scrub the data.
I'm trying to get only the earliest date to return. The first subquery (that starts with "select distinct address_id", with the MIN) works fine on it's own...no duplicates are returned. So it would seem that the left join (or just plain join...I've tried that too) couldn't possibly see the second h2.datecreated, since it doesn't even show up in the subquery. But when I run the whole query, it's returning 2 values for some ipc.mfgid's, one with the h2.datecreated that I want, and the other one that I don't want.
I know it's got to be something really simple, or something that just isn't possible. It really seems like it should work! This is MSSQL. Thanks!
select distinct ipc.mfgid as IPC, h2.datecreated,
case when ad.Address is null
then ad.buildingname end as Address, cast(trace.name as varchar)
+ '-' + cast(trace.Number as varchar) as ONT,
c.ACCOUNT_Id,
case when h.datecreated is not null then h.datecreated
else h2.datecreated end as Install
from equipmentjoin as ipc
left join historyjoin as h on ipc.id = h.EQUIPMENT_Id
and h.type like 'add'
left join circuitjoin as c on ipc.ADDRESS_Id = c.ADDRESS_Id
and c.GRADE_Code like '%hpna%'
join (select distinct address_id, equipment_id,
min(datecreated) as datecreated, comment
from history where comment like 'MAC: 5%' group by equipment_id, address_id, comment)
as h2 on c.address_id = h2.address_id
left join (select car.id, infport.name, carport.number, car.PCIRCUITGROUP_Id
from circuit as car (NOLOCK)
join port as carport (NOLOCK) on car.id = carport.CIRCUIT_Id
and carport.name like 'lead%'
and car.GRADE_Id = 29
join circuit as inf (NOLOCK) on car.CCIRCUITGROUP_Id = inf.PCIRCUITGROUP_Id
join port as infport (NOLOCK) on inf.id = infport.CIRCUIT_Id
and infport.name like '%olt%' )
as trace on c.ccircuitgroup_id = trace.pcircuitgroup_id
join addressjoin as ad (NOLOCK) on ipc.address_id = ad.id
The typical approach to only getting the lowest row is one of the following. You didn't bother to specify what version of SQL Server you're using, what you want to do with ties, and I have little interest to try to work this into your complex query, so I'll show you an abstract simplification for different versions.
SQL Server 2000
SELECT x.grouping_column, x.min_column, x.other_columns ...
FROM dbo.foo AS x
INNER JOIN
(
SELECT grouping_column, min_column = MIN(min_column)
FROM dbo.foo GROUP BY grouping_column
) AS y
ON x.grouping_column = y.grouping_column
AND x.min_column = y.min_column;
SQL Server 2005+
;WITH x AS
(
SELECT grouping_column, min_column, other_columns,
rn = ROW_NUMBER() OVER (ORDER BY min_column)
FROM dbo.foo
)
SELECT grouping_column, min_column, other_columns
FROM x
WHERE rn = 1;
This subqery:
select distinct address_id, equipment_id,
min(datecreated) as datecreated, comment
from history where comment like 'MAC: 5%' group by equipment_id, address_id, comment
Probably will return multiple rows because the comment is not guaranteed to be the same.
Try this instead:
CROSS APPLY (
SELECT TOP 1 H2.DateCreated, H2.Comment -- H2.Equipment_id wasn't used
FROM History H2
WHERE
H2.Comment LIKE 'MAC: 5%'
AND C.Address_ID = H2.Address_ID
ORDER BY DateCreated
) H2
Switch that to OUTER APPLY in case you want rows that don't have a matching desired history entry.

Resources