Pergunta

I have a query for a dynamicreport as a datasource. The result till now is:

enter image description here

There are 3 queries connected with UNION. Line 1 all data accumulated for the company. Line 2 all Data for the location and line 3 the detail data.

It is like a tree. But my problem is, that the accumulation is not correct (AnzahlMinuten). Is there an other way to display this data in a dynamicreport. This 3 queries can be very time intense. I also use the RANK() function because i got multiple entries for the time a license is used.

If there are no other easier solutions, where is my fault in the connected queries with union, so that the accumulation is not correct?

SELECT Gesellschaftsname,Standortname,Lizenzname,Abteilungsname,Kostenstelle,    
COUNT(DISTINCT username) AS AnzahlUser,
SUM(DISTINCT RuntimeMinute) AS AnzahlMinuten,

1 FROM  (SELECT * FROM(SELECT DISTINCT Standortname,
                        DATEPART(YEAR,PK_Date) AS Jahr,
                        DATEPART(month,PK_Date) AS Monat,
                        Lizenzname,COUNT(DISTINCT username) AS AnzUser,
                        SUM(DISTINCT DATEDIFF(minute,starttime ,pk_date))  AS RuntimeMinute,
                        starttime,
                        username,
                        pk_date,
                        Abteilungsname,
                        Gesellschaftsname,
                        Kostenstelle,
                        RANK() Over (PARTITION BY starttime ORDER BY pk_date DESC) As Rank 
                        FROM BenutzerLizenz,Benutzer,Abteilung,Lizenz,Standort,Gesellschaft,Kostenstelle
                        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  PK_ID_Abteilung = FK_ID_Abteilung AND PK_ID_Gesellschaft = FK_ID_Gesellschaft AND PK_ID_Kostenstelle = FK_ID_Kostenstelle AND
                        DATEPART(month,PK_Date) IN ('06','07') AND 
                        DATEPART(YEAR,PK_Date) = '2013' AND
                        Lizenzname IN ('DESIGNER','iman_nth') AND 
                        Standortname IN ('Unterlüß','Neuenburg') 
                        GROUP BY Standortname, Lizenzname, starttime, pk_date, username ,Abteilungsname, Kostenstelle, Gesellschaftsname) tmp 
                        WHERE Rank = 1)tmp2 GROUP BY Standortname,Lizenzname,Abteilungsname, Kostenstelle, Gesellschaftsname

UNION

SELECT Gesellschaftsname,'','','','',
COUNT(DISTINCT username) AS AnzahlUser,
SUM(DISTINCT RuntimeMinute) AS AnzahlMinuten,2
FROM  (SELECT * FROM(SELECT DISTINCT Gesellschaftsname,
                        DATEPART(YEAR,PK_Date) AS Jahr,
                        DATEPART(month,PK_Date) AS Monat,
                        COUNT(DISTINCT username) AS AnzUser,
                        SUM(DISTINCT DATEDIFF(minute,starttime ,pk_date))  AS RuntimeMinute,
                        starttime,
                        username,
                        pk_date,
                        RANK() Over (PARTITION BY starttime ORDER BY pk_date DESC) As Rank 
                        FROM BenutzerLizenz,Benutzer,Lizenz,Standort,Gesellschaft
                        WHERE BenutzerLizenz.PK_ID_user=Benutzer.PK_ID_user AND BenutzerLizenz.PK_ID_lic=Lizenz.PK_ID_lic AND  PK_ID_Gesellschaft = FK_ID_Gesellschaft AND
                        DATEPART(month,PK_Date) IN ('06','07') AND 
                        DATEPART(YEAR,PK_Date) = '2013' AND
                        Lizenzname IN ('DESIGNER','iman_nth') AND 
                        Standortname IN ('Unterlüß','Neuenburg') 
                        GROUP BY Gesellschaftsname,starttime, pk_date, username) tmp 
                        WHERE Rank = 1)tmp2 GROUP BY Gesellschaftsname

UNION

SELECT '',Standortname,'','','',
COUNT(DISTINCT username) AS AnzahlUser,
SUM(DISTINCT RuntimeMinute) AS AnzahlMinuten,3
FROM  (SELECT * FROM(SELECT DISTINCT Standortname,
                        DATEPART(YEAR,PK_Date) AS Jahr,
                        DATEPART(month,PK_Date) AS Monat,
                        COUNT(DISTINCT username) AS AnzUser,
                        SUM(DISTINCT DATEDIFF(minute,starttime ,pk_date))  AS RuntimeMinute,
                        starttime,
                        username,
                        pk_date,
                        RANK() Over (PARTITION BY starttime 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 PK_ID_Abteilung = FK_ID_Abteilung AND
                        DATEPART(month,PK_Date) IN ('06','07') AND 
                        DATEPART(YEAR,PK_Date) = '2013' AND
                        Lizenzname IN ('DESIGNER','iman_nth') AND 
                        Standortname IN ('Unterlüß','Neuenburg') 
                        GROUP BY Standortname, starttime, pk_date, username) tmp 
                        WHERE Rank = 1)tmp2 GROUP BY Standortname
                        ORDER BY 2
Foi útil?

Solução

I think the main issue is with the use of "distinct." This is not a coding problem. When summing distinct on multiple grouping levels, the totals of sub-groups may be greater than the total of the top group. For example:

GroupId Value
1       1
1       2
1       3
2       2
2       4
2       5

Sum(distinct value) on group 1 = 6
sum(distinct value) on group 2 = 11
sum(distinct value) on both groups = 15

Also, in general, it sounds like you are asking for a neater way to solve this problem of multiple grouping levels in a single recordset. I did something like this at a previous job:

sql fiddle

The idea is that you build the list of possible groups first in a CTE as

Level1 Level2 Level3
A      NULL   NULL
A      AA     NULL
A      AB     NULL
A      AA     AAA
A      AA     AAB
A      AB     ABA
A      AB     ABB

then join that to your data on the three levels and group by Level1, Level2, Level3. It's a lot cleaner.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top