views:

61

answers:

1

I have two great tables that I would like to use as foundation for an even greater third table!

The output depends on date interval, like 09/01/2010 - 09/03/2010

Example of Output from TABLE A - - (ALLOCATED Testers)

Date            Country        Allocated testers
09/01/2010      Nigeria           0
09/02/2010      Nigeria           1
09/03/2010      Nigeria         134

09/01/2010      China             2
09/02/2010      China             0
09/03/2010      China            14

09/01/2010      Chile             3
09/02/2010      Chile             4
09/03/2010      Chile             0

*************

Example of Output from TABLE B - - (ABSENT Testers)

Date            Country        Absent testers
09/01/2010      Nigeria           0
09/02/2010      Nigeria           7
09/03/2010      Nigeria           0

09/01/2010      China             2
09/02/2010      China             0
09/03/2010      China             0

09/01/2010      Chile             1
09/02/2010      Chile             0
09/03/2010      Chile             0

*************

Example of WANTED output from TABLE C (ALLOCATED AND ABSENT Testers)

Date            Country        Allocated testers    Absent testers
09/01/2010      Nigeria           0                 0
09/02/2010      Nigeria           1                 7
09/03/2010      Nigeria         134                 0

09/01/2010      China             2                 2
09/02/2010      China             0                 0
09/03/2010      China            14                 0

09/01/2010      Chile             3                 2
09/02/2010      Chile             4                 0
09/03/2010      Chile             0                 0

And here is some SQL code generating the above shown output... (yes, they work)

TABLE A

WITH Calendar AS (SELECT     CAST(@StartDate AS datetime) AS Date
     UNION ALL
     SELECT     DATEADD(d, 1, Date) AS Expr1
     FROM         Calendar AS Calendar_1
     WHERE     (DATEADD(d, 1, Date) < @EndDate))
    SELECT     C.Date, C2.Country, COALESCE (SUM(R.[Amount of people per day needed]), 0) AS [Allocated testers]
     FROM         Calendar AS C CROSS JOIN
                            Country AS C2 LEFT OUTER JOIN
                            Requests AS R ON C.Date BETWEEN R.[Start date] AND R.[End date] AND R.CountryID = C2.CountryID
     GROUP BY C.Date, C2.Country OPTION (MAXRECURSION 0)

TABLE B

WITH Calendar AS (SELECT     CAST(@StartDate AS datetime) AS Date
     UNION ALL
     SELECT     DATEADD(d, 1, Date) AS Expr1
     FROM         Calendar AS Calendar_1
     WHERE     (DATEADD(d, 1, Date) < @EndDate))
    SELECT     C.Date, C2.Country, COALESCE (COUNT(PA.PeopleID), 0) AS [Absent testers]
     FROM         Calendar AS C CROSS JOIN
                            Country AS C2 INNER JOIN
                            Roles AS R INNER JOIN
                            People AS P ON R.RolesID = P.RolesID ON C2.CountryID = P.CountryID LEFT OUTER JOIN
                            PeoplesAbsence AS PA ON C.Date BETWEEN PA.StartDate AND PA.EndDate AND P.PeopleID = PA.PeopleID
     WHERE     (R.Role = 'Tester')
     GROUP BY C.Date, C2.Country OPTION (MAXRECURSION 0)

TABLE C is the one I need help to create :-)

NOTE: I would like to see some kind of example code, to get started!

NOTE ALSO: I don´t want to solve this with Views in SQL Server, because it just doesn´t work... - I need that 3:rd table ;-)


SOLVED! Got the solution from tdammers (thanks!), and this is how it looks when implemented:

WITH Calendar AS (SELECT     CAST(@StartDate AS datetime) AS Date
UNION ALL
SELECT
    DATEADD(d, 1, Date) AS Expr1
FROM
    Calendar AS Calendar_1
WHERE
    (DATEADD(d, 1, Date) < @EndDate))


SELECT a.Date, a.Country, a.[Allocated testers], b.[Absent testers] FROM ( SELECT
    C.Date, C2.Country, COALESCE (SUM(R.[Amount of people per day needed]), 0) AS [Allocated testers]
FROM
    Calendar AS C
CROSS JOIN
    Country AS C2
LEFT OUTER JOIN
    Requests AS R 
    ON
        C.Date BETWEEN R.[Start date] AND R.[End date] AND R.CountryID = C2.CountryID
GROUP BY
    C.Date, C2.Country ) as a LEFT OUTER JOIN ( SELECT     C.Date, C2.Country, COALESCE (COUNT(PA.PeopleID), 0) AS [Absent testers]
     FROM         Calendar AS C CROSS JOIN
                            Country AS C2 INNER JOIN
                            Roles AS R INNER JOIN
                            People AS P ON R.RolesID = P.RolesID ON C2.CountryID = P.CountryID LEFT OUTER JOIN
                            PeoplesAbsence AS PA ON C.Date BETWEEN PA.StartDate AND PA.EndDate AND P.PeopleID = PA.PeopleID
     WHERE     (R.Role = 'Tester')
     GROUP BY C.Date, C2.Country ) as b ON a.date = b.date AND a.country = b.country
+2  A: 

Table C shouldn't be a table, but rather a view.

tdammers
No, I want it to be a table!
Jack Johnstone
Oh wait, forget that. The first two aren't tables either, they're just select queries. I don't think you actually know what an SQL table is in the first place.As to your original problem: - create a view from the first query - create a view from the second query - use a `join` on both views to accumulate the desired output for query C
tdammers
OK - I admit that they are select queries! I was just joking before. The trouble is that I want a THIRD select query, not views. Because I can´t create views of them since they contains parameters, instead I have to create User-Defined-Functions, and that to me seems like to much right now - so give me a tip on how the third query should be designed and stop talking about Views! ;-) And I actually know what an SQL table is, the problem was that I didn´t know what it wasn´t - but thanks for sorting that out. I will never call a select query a table again, I promise!
Jack Johnstone
Right. Instead of putting the first two queries into views, you can put them into subqueries, and perform a join on those. Although your queries seriously suggest a pretty bad database design - with a properly normalized schema, this would be ridiculously easy.
tdammers
Well, I don´t agree on that "pretty bad database design" opinion - but aside from that, would you mind showing an example IN CODE of the ridiculously easy sub-query operation you suggest? That would make things a bit easier to me, and I´m sure you want to help me...? You don´t have to dig into my example, just show me something "generic" if you so prefer :-)
Jack Johnstone
Something like:SELECT a.date, a.country, a.num, b.numFROM ( /* first subquery here */ ) as aINNER JOIN ( /* second subquery here */ ) as bON a.date = b.date AND a.country = b.country
tdammers
Thanks tdammers, it worked!!! - see my updated Question to see the result if interested.One problem left though, might not be possible to fix, as it has to do with the db-design ;-) The thing is that the WHERE clause sorts out countries that have no Absent people, and I want to show them to in the output list - any ideas on workarounds? And again, a big thank you!
Jack Johnstone
Actually managed to solve that last issue myself with an LEFT OUTER JOIN...
Jack Johnstone
Does anyone (for example tdammers...) know if there is any easy way to sum "a.num, b.num" up in a fifth column? Like SUM(a.num + b.num) in the SELECT statement?
Jack Johnstone
Exactly like that, just without the SUM().
tdammers
tdammers, you are the best!
Jack Johnstone