根据列中的值查询到 return 多行

Query to return multiple rows based on the value in a column

我有一个来源 table,其中的项目的开始日期和持续时间以月为单位。我正在寻找为 PowerBI 编写一个 PowerQuery,它将为项目的每个月创建一行,计算月份。例如:

Source:
Project(string) | Date (ms timestamp)    | Duration (integer)
A               | Jan-2022               | 3
B               | Sep-2022               | 2
    
Result:
Project | Date
A       | Jan-2022
A       | Feb-2022
A       | Mar-2022
B       | Sep-2022
B       | Oct-2022

不确定从哪里开始或该查询应该是什么样子。有什么想法吗?

编辑:更改示例 tables 以使其可读

编辑:源 table 中的日期以毫秒时间戳格式提供(例如 1641024000000)。我对结果 table 的意图是让它们采用人类可读的日期格式。

出于某种原因,sqlfiddle 对我来说很失败,所以我在 db-fiddle 中使用 postgres 而不是 ms-sql 做了一个例子。

您想要完成的工作可以通过递归 CTE 完成,MS-SQL 中的语法略有不同,但这应该可以帮助您完成大部分工作。

WITH RECURSIVE project_dates AS(
  SELECT 
      start_date as starting_date,
      CAST(start_date + duration*INTERVAL '1 month' as date) as end_date,
      project
  FROM projects
  UNION
    SELECT 
        CAST(starting_date + INTERVAL '1 month' as date),
        pd.end_date,
        p.project
    FROM projects p
        JOIN project_dates pd ON pd.project = p.project 
    WHERE CAST(starting_date + INTERVAL '1 month' as date) < pd.end_date
) 
SELECT starting_date, project FROM project_dates
ORDER BY project, starting_date

我使用你的日期得出的结果看起来是这样的。

您可以通过 link 查看我在 db-fiddle 上的回答:https://www.db-fiddle.com/f/iS7uWFGwiMbEmFtNmhsiWt/0

这是在 Power Query 中执行此操作的一种方法。

  • 将代码粘贴到空白查询中。
  • 然后更改源行以加载您的实际数据table。
    • 我使用了 Excel table 作为来源,但你可以使用任何东西。
    • 我在源代码中也有 unix 时间戳 table,在 M 代码中将其转换为 PQ 日期。
    • 如果您的所有时间戳都不等于月初,则可能需要一些额外的逻辑。
  • 阅读代码注释并探索应用步骤以了解算法
let

//Read in the Source data
    Source = Excel.CurrentWorkbook(){[Name="Table27"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Project", type text}, {" Date", Int64.Type}, {" Duration", Int64.Type}}),

//convert date from unixTime in milliseconds to a PQ date
    unixTime = Table.TransformColumns(#"Changed Type",{" Date", each #duration(0,0,0,_/1000)+#date(1970,1,1)}),

//add custom column with a List of the desired dates
    #"Added Custom" = Table.AddColumn(unixTime, "Months", each 
        List.Accumulate(
            {0..[#" Duration"]-1},
            {},
            (state,current)=> state & {Date.AddMonths([#" Date"],current)})),

//Remove unneeded columns
//Expand the list and set the data thype
    #"Removed Columns" = Table.RemoveColumns(#"Added Custom",{" Date", " Duration"}),
    #"Expanded Months" = Table.ExpandListColumn(#"Removed Columns", "Months"),
    #"Changed Type1" = Table.TransformColumnTypes(#"Expanded Months",{{"Months", type date}})
in
    #"Changed Type1"

试试下面

将您的毫秒数除以 86400000 并将其添加到 1/1/1970 以获得日期

根据持续时间创建一个数组,扩展到行,将其添加到开始日期

删除多余的列

let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
ConvertToDays = Table.TransformColumns(Source,{{"Date", each Number.RoundDown(Number.From(_) / 86400000)}}),
#"Added Custom" = Table.AddColumn(ConvertToDays, "Custom", each Date.AddDays(#date(1970,1,1),18993)),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "Custom.1", each List.Numbers(0,[Duration])),
#"Expanded Custom.1" = Table.ExpandListColumn(#"Added Custom1", "Custom.1"),
#"Added Custom2" = Table.AddColumn(#"Expanded Custom.1", "Custom.2", each Date.AddMonths([Custom],[Custom.1]), type date),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom2",{"Date", "Duration", "Custom", "Custom.1"}),
#"Renamed Columns" = Table.RenameColumns(#"Removed Columns",{{"Custom.2", "Date"}}),
TextDate = Table.AddColumn(#"Renamed Columns", "TextDate", each Date.ToText([Date],"MMM-yy"))
in  TextDate