【问题标题】:Join table on itself for unique row combinations for calculations连接表本身以获得用于计算的唯一行组合
【发布时间】:2012-12-28 19:59:16
【问题描述】:

我有一个表,我需要使用它来构建一个结果集,其中表中的某些行是结果集中的列。我开始将LEFT JOINs 多次链接在桌子上,但我需要消除与集合中已有的另一个结果的不同组合的结果:

例如,如果我得到 1、21、25 作为结果列,我不能在结果中包含这些数字的任何其他组合。

我的表定义是:

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

我目前的查询是:

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

我知道这是错误的,但这是我需要的超集。在上述查询的结果中,我可以获得 J1.KPI、J2.KPI、J3.KPI 或 J1.KPI、J3.KPI、J2.KPI 或任何其他组合。

我的预期结果是:

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

对于每个部门、月份和年份

其中 KPIA、KPIB 或 KPIC = 1、21 或 25,但每个部门仅存在 1、21、25 的 1 个组合|月|年

编辑

为了更清楚地说明预期结果,使用上述查询,我​​得到以下结果:

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

我需要这样做,这样我的结果就只能是前 3 个结果中的任何一个,然后是最后一个......例如:

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

【问题讨论】:

  • 请向我们展示您的预期结果。
  • @bonCodigo 我添加了我的预期输出。
  • WHERE J1.KPI = 1 OR J1.KPI = 21 OR J1.KPI = 25 可以替换为J1.KPI IN (1, 21, 25)。无论如何,您的观点发生了什么变化?
  • 为简洁起见,我删除了该视图...它与手头的问题无关。糟糕,刚刚意识到我忘了从第一个 JOIN 中删除“ON”。

标签: sql sql-server join left-join


【解决方案1】:

我认为您正在寻找像这样的 PIVOT 表运算符:

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

这将为您提供表单中的数据:

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

请注意:这将为您提供具有所有值 1、21 和 25 的 YearMonthDEVISION 的唯一组合,以及此查询的作用:

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

更新:如果您正在寻找至少有 1、21 或 25 之一的那些,只需删除 HAVING COUNT(DISTINCT KPI) = 3,但这会让您期望比这三个更多的值,在在这种情况下,它将忽略其他值并仅返回这三个值。它还将为它们的任何缺失值返回NULL,如下所示:

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 |

【讨论】:

  • 这很接近。不过,我需要能够处理没有针对特定部门的 KPI 的案例。我已经modified your example 展示了 C 部门缺少 KPI '21' 条目的情况。仍然应该有一个结果行只显示 KPIBVALUE 为 NULL。
  • @Ryan - 所以你正在寻找那些至少有 1 个或 21 个或 25 个而不是所有像 this example 我刚刚删除 HAVING COUNT(DISTINCT KPI) = 3 的人,但这会让你期待超过这些值,以防它们像 B 中那样更多,它还有一个 KPI 值,即 30,但是此查询将忽略它并仅返回这三个 KPI,它还将处理缺少一个 KPI 的情况它会返回NULL
【解决方案2】:

如果你没有大量的“ID”,你可以像这样转置这些值:

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

或者使用“OVER”子句来做同样的事情。

【讨论】:

    【解决方案3】:

    我认为您需要条件聚合。但我仍然不清楚结果是如何定义的。这可能会对您有所帮助:

    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
    

    【讨论】:

      【解决方案4】:

      也许您可以尝试以下方法:

      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
      

      然后是您想要的每个可能的 KPI 值的一个 LEFT JOIN。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-18
        • 2012-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-18
        相关资源
        最近更新 更多