【问题标题】:Cross join (pivot) with n-n table containing values [duplicate]与包含值的 n-n 表交叉连接(枢轴)[重复]
【发布时间】:2010-09-27 03:15:34
【问题描述】:

我有 3 张桌子:

TABLE MyColumn (
  ColumnId INT NOT NULL,
  Label VARCHAR(80) NOT NULL,
  PRIMARY KEY (ColumnId)
)

TABLE MyPeriod (
  PeriodId CHAR(6) NOT NULL, -- format yyyyMM
  Label VARCHAR(80) NOT NULL,
  PRIMARY KEY (PeriodId)
)

TABLE MyValue (
  ColumnId INT NOT NULL,
  PeriodId CHAR(6) NOT NULL,
  Amount DECIMAL(8, 4) NOT NULL,
  PRIMARY KEY (ColumnId, PeriodId),
  FOREIGN KEY (ColumnId) REFERENCES MyColumn(ColumnId),
  FOREIGN KEY (PeriodId) REFERENCES MyPeriod(PeriodId)
)

MyValue 的行仅在提供实际值时创建。

我希望我的结果以表格的方式显示:

Column   | Month 1 | Month 2 | Month 4 | Month 5 |
Potatoes |   25.00 |    5.00 |    1.60 |    NULL |
Apples   |    2.00 |    1.50 |    NULL |    NULL |

我已经成功创建了一个交叉连接:

SELECT
    MyColumn.Label AS [Column],
    MyPeriod.Label AS [Period],
    ISNULL(MyValue.Amount, 0) AS [Value]
FROM
    MyColumn CROSS JOIN
    MyPeriod LEFT OUTER JOIN
    MyValue ON (MyValue.ColumnId = MyColumn.ColumnId AND MyValue.PeriodId = MyPeriod.PeriodId)

或者,在 linq 中:

from p in MyPeriods
from c in MyColumns
join v in MyValues on new { c.ColumnId, p.PeriodId } equals new { v.ColumnId, v.PeriodId } into values
from nv in values.DefaultIfEmpty()
select new {
    Column = c.Label,
    Period = p.Label,
    Value = nv.Amount
}

并了解了如何在 linq(herehere)中创建枢轴:

(假设 MyDatas 是包含上一个查询结果的视图):

from c in MyDatas
group c by c.Column into line
select new
{
  Column = line.Key,
  Month1 = line.Where(l => l.Period == "Month 1").Sum(l => l.Value),
  Month2 = line.Where(l => l.Period == "Month 2").Sum(l => l.Value),
  Month3 = line.Where(l => l.Period == "Month 3").Sum(l => l.Value),
  Month4 = line.Where(l => l.Period == "Month 4").Sum(l => l.Value)
}

但我想找到一种方法来创建一个结果集,如果可能的话,Month1, ... 属性是动态的。

注意:导致 n+1 查询的解决方案:

from c in MyDatas
group c by c.Column into line
select new
{
    Column = line.Key,
    Months =
        from l in line
        group l by l.Period into period
        select new
        {
            Period = period.Key,
            Amount = period.Sum(l => l.Value)
        }
}

【问题讨论】:

    标签: sql linq pivot cross-join


    【解决方案1】:

    您是否有日历期间 (1-12) 或会计期间(1-12 或 1-13,具体取决于年份)?

    你会只运行一年的报告吗?

    如果可能,我会将 PeriodId 分为 Year 和 Period 两个字段。这将使选择特定年份变得更容易。查询会更简单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-19
      相关资源
      最近更新 更多