JOINING Results from two SELECT stataments each with their own WHERE criteria and GROUPING

StackOverflow https://stackoverflow.com/questions/19076978

  •  29-06-2022
  •  | 
  •  

Question

I have the following two Select statements -

SELECT * 
FROM tblAllocations
WHERE AllocID IN
(
    SELECT MAX(AllocID)    
    FROM tblAllocations
    WHERE FeeEarner = 'KLW' AND [Date] <= '2013-12-31'
    GROUP BY FeeEarner, CaseNo

and

SELECT UserID, CaseNo, SUM(Fees) AS [Fees]
FROM tblTimesheetEntries
WHERE UserID = 'KLW' AND [Date] <= '2013-12-31'
GROUP BY UserID, CaseNo

Which return the following results -

Results of Separate Queries

What I want is to combine them in a Select statement which extracts some fields from the First Query and other fields from the Second Query. Based on the above results there should be just 5 lines returned, three of which would have fields from both Query, and two would only have fields from one Query (hence it would have some NULL values)

I tried the following -

SELECT q1.CaseNo, q1.FeeEarner, 
       q2.Fees AS [Fees], 
       q1.Fees AS [Billed], 
      (q2.Fees - q1.Fees) AS WIP
FROM
(
    SELECT * 
    FROM tblAllocations
    WHERE AllocID IN
    (
        SELECT MAX(AllocID)    
        FROM tblAllocations
        WHERE FeeEarner = 'KLW'
        AND [Date] <= '2013-12-31'
        GROUP BY FeeEarner, CaseNo
    )
) AS q1,
(
    SELECT UserID, CaseNo, SUM(Fees) AS [Fees]
    FROM tblTimesheetEntries
    WHERE UserID = 'KLW'
    AND [Date] <= '2013-12-31'
    GROUP BY UserID, CaseNo
) AS q2

However this acts like a Cross Join and gives me 15 lines as follows -

Erroneous Results

Could some one advice me how to combine these two queries correctly so as to only return 5 lines.

Était-ce utile?

La solution

Below is the corrected query:

 SELECT q1.CaseNo, q1.FeeEarner, 
           q2.Fees AS [Fees], 
           q1.Fees AS [Billed], 
          (q2.Fees - q1.Fees) AS WIP
    FROM
    (
    SELECT * 
    FROM tblAllocations
    WHERE AllocID IN
    (
    SELECT MAX(AllocID)    
    FROM tblAllocations
    WHERE FeeEarner = 'KLW'
    AND [Date] <= '2013-12-31'
    GROUP BY FeeEarner, CaseNo
    )
    ) AS q1,
    (
    SELECT UserID, CaseNo, SUM(Fees) AS [Fees]
    FROM tblTimesheetEntries
    WHERE UserID = 'KLW'
    AND [Date] <= '2013-12-31'
    GROUP BY UserID, CaseNo
    ) AS q2
    where q1.CaseNo = q2.CaseNo

Autres conseils

It's doing a cross join because you're not saying how q1 and q2 are "related" (joined).

Also, since you want five rows (that is, all rows in tblTimesheetEntries regardless of a match in tblAllocations), you should use a right join (or a left but inverting q1 and q2):

SELECT
  q2.CaseNo,
  q1.FeeEarner,
  q2.Fees AS [Fees],
  q1.Fees AS [Billed],
  (q2.Fees - q1.Fees) AS WIP
FROM (
  SELECT * FROM tblAllocations
  WHERE AllocID IN (
    SELECT MAX(AllocID)
    FROM tblAllocations
    WHERE FeeEarner = 'KLW' AND [Date] <= '2013-12-31'
    GROUP BY FeeEarner, CaseNo
  )) AS q1
RIGHT JOIN (
  SELECT UserID, CaseNo, SUM(Fees) AS[Fees]
  FROM tblTimesheetEntries
  WHERE UserID = 'KLW'
  AND [Date] <= '2013-12-31'
  GROUP BY UserID, CaseNo
) AS q2
  ON q1.CaseNo = q2.CaseNo

SqlFiddle here.

I would start with your second query, then LEFT-JOIN to your first. The second query has the corresponding case numbers 15, 25 and 33 which would show all columns, but also case 5 and 12 which would result with NULL for the other columns.

select 
      AllThese.UserID,
      AllThese.Fees,
      MaxAlloc.*
   from
      ( SELECT 
              UserID,
              CaseNo, 
              SUM(Fees) AS [Fees]
           FROM 
              tblTimesheetEntries
           WHERE 
                  UserID = 'KLW'
              AND [Date] <= '2013-12-31'
           GROUP BY 
              UserID, 
              CaseNo ) AllThese
      LEFT JOIN
      ( SELECT * 
           FROM tblAllocations
           WHERE AllocID IN
             ( SELECT MAX(AllocID)
                  FROM tblAllocations
                  WHERE FeeEarner = 'KLW'
                    AND [Date] <= '2013-12-31'
                  GROUP BY FeeEarner, CaseNo )) MaxAlloc
         on AllThese.CaseNo = MaxAlloc.CaseNo
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top