Domanda

I have a problem with a SQL-Query. I want to count the runtime of a used application. But in the database the date value is inserted more then one time. I only need the highest value of the pk_date column and no duplicated entries from the starttime column.

Here is the SQL-Query:

SELECT DISTINCT Standortname,
DATEPART(YEAR,PK_Date) AS Jahr,
DATEPART(month,PK_Date) AS Monat,
Lizenzname,
COUNT(DISTINCT username) AS AnzahlUser,
SUM(DISTINCT DATEDIFF(minute,starttime ,pk_date))  AS RuntimeMinute,
endtime,
pk_date

FROM BenutzerLizenz,Benutzer,Abteilung,Lizenz,Standort
WHERE 
BenutzerLizenz.PK_ID_user=Benutzer.PK_ID_user
AND BenutzerLizenz.PK_ID_lic=Lizenz.PK_ID_lic
AND PK_ID_standort=FK_ID_standort
AND DATEPART(month,PK_Date) = '04'
AND DATEPART(YEAR,PK_Date) = '2013'
AND Lizenzname = 'iman_1st'
AND Standortname = 'Unterlüß'

GROUP BY
 Standortname,
 DATEPART(YEAR,PK_Date),
 DATEPART(month,PK_Date),
 Lizenzname,
 starttime,
 endtime,
 pk_date

Here is the result:

... RuntimeMinute   starttime                   pk_date
    339         2013-04-11 11:05:00.0000000 2013-04-11 16:44:37.9650000
    346         2013-04-11 11:05:00.0000000 2013-04-11 16:51:25.4800000
    356         2013-04-11 11:05:00.0000000 2013-04-11 17:01:19.9670000
    475         2013-04-11 10:06:00.0000000 2013-04-11 18:01:15.6620000

The first three above runtimes are from the same user and session, the last one is from another user and session. I only want to count and sum the last runtimes from the same starttime and the maximum date inserted (pk_date) -> 356 + 475 is the value that I would like to have.

In another similar query all values are accumulated (the columns starttime, endtime, pk_date are not included in it, so the query builds the sum of all runtime values for all users). I tried to use DISTINCT and MAX(pk_date) but it didn't work as expected. Do I have to use Sub-Queries?

È stato utile?

Soluzione

I would use RANK() function for this.

SELECT * FROM
(
SELECT DISTINCT Standortname,
DATEPART(YEAR,PK_Date) AS Jahr,
DATEPART(month,PK_Date) AS Monat,
Lizenzname,
COUNT(DISTINCT username) AS AnzahlUser,
SUM(DISTINCT DATEDIFF(minute,starttime ,pk_date))  AS RuntimeMinute,
endtime,
pk_date,
RANK() Over (PARTITION BY username ORDER BY pk_date DESC) As Rank

FROM BenutzerLizenz,Benutzer,Abteilung,Lizenz,Standort
WHERE 
BenutzerLizenz.PK_ID_user=Benutzer.PK_ID_user
AND BenutzerLizenz.PK_ID_lic=Lizenz.PK_ID_lic
AND PK_ID_standort=FK_ID_standort
AND DATEPART(month,PK_Date) = '04'
AND DATEPART(YEAR,PK_Date) = '2013'
AND Lizenzname = 'iman_1st'
AND Standortname = 'Unterlüß'

GROUP BY
 Standortname,
 DATEPART(YEAR,PK_Date),
 DATEPART(month,PK_Date),
 Lizenzname,
 starttime,
 endtime,
 pk_date,
 username
) tmp where Rank=1

The RANK() functions ranks each row of a result set in the order defined by ORDER BY. Used with PARTITION BY, you can further partition the data for ranking.

Since you already have the data that you need, you will partition the result by username and rank the pk_date in order to get the highest one.

Altri suggerimenti

It sounds like you want to make a query that only keeps the max(pk_date) for each beginning time and user/session combination. Then add that query to your FROM clause (let's say as adhoc). Then you put in the WHERE clause pk_date = adhoc.pkdate AND username = adhoc.username etc...

Simplified example:

(SELECT username, startdate, max(pk_date) as pk_date 
FROM <whatever> 
GROUP BY username, startdate) (= <new>)

now, in your main query...

SELECT ... FROM ...,<new> adhoc 
WHERE adhoc.username = username 
AND adhoc.startdate = startdate 
AND pk_date = adhoc.pk_date ... 

Does this help?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top