1

I have a table that I need to use to build a result set from where certain rows from the table are columns in the result set. I started to chain LEFT JOINs together on the table multiple times but I need to eliminate results that are a different combination of another result already in the set:

For example, if I get 1, 21, 25 as result columns, I can't have ANY other combination of those numbers in the results.

My table definition is:

Table tblKPIDetails
Column Month int
Column Year int
Column Division varchar(3)
Column KPI int
Column Value decimal(18,4)

My current query is:

SELECT *
FROM tblKPIDetails J1
    LEFT JOIN tblKPIDetails J2 ON J2.Month = J1.Month AND J2.Year = J1.Year  AND J2.Division = J1.Division AND NOT(J2.KPI = J1.KPI ) AND (J2.KPI = 1 OR J2.KPI = 21 OR J2.KPI = 25)
    LEFT JOIN tblKPIDetails J3 ON J3.Month = J1.Month AND J3.Year = J1.Year  AND J3.Division = J1.Division AND NOT(J3.KPI = J1.KPI ) AND (J3.KPI = 1 OR J3.KPI = 21 OR J3.KPI = 25)
WHERE J1.KPI = 1 OR J1.KPI = 21 OR J1.KPI = 25

I know this is wrong, but it's a super-set of what I need. In the results from the query above, I can get J1.KPI, J2.KPI, J3.KPI or J1.KPI, J3.KPI, J2.KPI, or any other combination.

My expected result would be:

Division | Month | Year | KPIA | KPIAValue | KPIB | KPIBValue | KPIC | KPICValue

for each division, month, and year

where KPIA, KPIB, or KPIC = 1, 21, or 25 but only 1 combination of 1,21,25 exists per division|month|year

EDIT

To clarify the expected results a little more, using the above query, I'm getting the following results:

Division | Month | Year | KPIA | KPIAValue | KPIB | KPIBValue | KPIC | KPICValue
--------------------------------------------------------------------------------
000          1     2012     1      1000       21      2000       25     3000
000          1     2012    21      2000        1      1000       25     3000
000          1     2012    25      3000       21      2000        1     1000
111          1     2012     1      555        21      10000      25     5000

I need to make it so my results would only be ANY 1 of the first 3 results and then the last one...for example:

Division | Month | Year | KPIA | KPIAValue | KPIB | KPIBValue | KPIC | KPICValue
--------------------------------------------------------------------------------
000          1     2012    25      3000       21      2000        1     1000
111          1     2012     1      555        21      10000      25     5000
4

4 回答 4

2

I think you are looking for the PIVOT table operator like so:

SELECT 
  Devision,
  Month, 
  Year,
  [1]  AS KPIAValue,
  [21] AS KPIBValue,
  [25] AS KPICValue
FROM
(
  SELECT t1.*
  FROM tblKPIDetails t1
  INNER JOIN
  (
    SELECT Month, Year, Devision
    FROM tblKPIDetails
    WHERE KPI IN(1, 21, 25)
    GROUP BY Month, Year, Devision
    HAVING COUNT(DISTINCT KPI) = 3
  ) t2 ON t1.Month = t2.Month AND t1.Year = t2.Year 
  AND t1.Devision = t2.Devision
) t
PIVOT
(
  MAX(Value)
  FOR KPI IN([1], [21], [25])) p;

SQL Fiddle Demo

This will give you the data in the form:

| DEVISION | MONTH | YEAR | KPIAVALUE | KPIBVALUE | KPICVALUE |
---------------------------------------------------------------
|        A |     2 | 2012 |        16 |        16 |        16 |
|        B |    10 | 2012 |        16 |        18 |        20 |

Note that: This will give you the only combination of the Year, Month, DEVISION that have all the values 1, 21 and 25, and that what this query do:

SELECT Month, Year, Devision
FROM tblKPIDetails
WHERE KPI IN(1, 21, 25)
GROUP BY Month, Year, Devision
HAVING COUNT(DISTINCT KPI) = 3

Update: If you are looking for those that had at least one of 1, 21 or 25, just remove the HAVING COUNT(DISTINCT KPI) = 3, but this will make you expect more values than these three, in this case it will ignore other values and return only those three. Also it will return NULL for any of the missing values of them like so:

SELECT 
  Devision,
  Month, 
  Year,
  [1]  AS KPIAValue,
  [21] AS KPIBValue,
  [25] AS KPICValue
FROM
(
  SELECT t1.*
  FROM tblKPIDetails t1
  INNER JOIN
  (
    SELECT Month, Year, Devision
    FROM tblKPIDetails
    WHERE KPI IN(1, 21, 25)
    GROUP BY Month, Year, Devision
  ) t2 ON t1.Month = t2.Month AND t1.Year = t2.Year 
  AND t1.Devision = t2.Devision
) t
PIVOT
(
  MAX(Value)
  FOR KPI IN([1], [21], [25])) p;

Updated SQL Fiddle Demo

| DIVISION | MONTH | YEAR | KPIAVALUE | KPIBVALUE | KPICVALUE |
---------------------------------------------------------------
|        A |     2 | 2012 |      15.5 |      15.5 |      15.5 |
|        B |    10 | 2012 |      15.5 |      17.5 |     20.24 |
|        C |    12 | 2012 |      15.5 |    (null) |     20.24 |
于 2012-12-28T20:09:09.203 回答
0

If you don't have a large number of "IDs", you could just transpose the values like this:

select 
[Month],
[Year],
Division,
sum(case when KPI = 1 then Value else null end) as KPI1,
sum(case when KPI = 21 then Value else null end) as KPI21,
sum(case when KPI = 25 then Value else null end) as KPI25
from tblKPIDetails
group by 
[Month],
[Year],
Division
order by 
[Month],
[Year],
Division

Or same thing by using the "OVER" clause.

于 2012-12-28T20:22:18.750 回答
0

I think you want a conditional aggregation. But it is still not clear to me how the results are being defined. This might help you on your way:

SELECT Division, Month, Year,
       1, max(case when kpi = 1 then value end) as kpi1value,
       21, max(case when kpi = 21 then value end) as kpi21value, 
       25, max(case when kpi = 25 then value end) as kpi25value,
FROM tblKPIDetails J1
于 2012-12-28T20:22:27.977 回答
0

maybe you can try the following:

SELECT DISTINCT
t.Division,
t.Month, 
t.Year,
KA.Value  AS KPIAValue,
KB.Value AS KPIBValue,
KC.Value AS KPICValue
FROM
tblKPIDetails t
LEFT JOIN tblKPIDetails KA ON t.Division = KA.Division and t.Month = KA.month and  .year = KA.year and KA.KPI = 1
LEFT JOIN tblKPIDetails KB ON t.Division = KB.Division and t.Month = KB.month and t.year = KB.year and KB.KPI = 21
LEFT JOIN tblKPIDetails KC ON t.Division = KC.Division and t.Month = KC.month and t.year = KC.year and KC.KPI = 25

Then is one LEFT JOIN for each possible KPI value you want.

于 2012-12-28T21:45:59.860 回答