【问题标题】:passing a cell value into SQL query using Power Query Editor in Excel使用 Excel 中的 Power Query 编辑器将单元格值传递到 SQL 查询
【发布时间】:2020-11-16 21:38:47
【问题描述】:

我正在使用 Excel Power Query Editor 来查询我的数据库以将信息提取到 Excel 中,以便我可以轻松地操作这些信息以用于报告目的。我在 Microsoft SQL 中编写了一个查询并将其粘贴到 Power Query 编辑器中。我有一个非常愚蠢的查询,只是使用下面代码片段中显示的参数表和函数按表中的日期过滤数据。

fParameters

query being filtered

fParameters 只是抓取一个包含 2 个包含开始和结束日期(周开始,周末)的单元格的表格。该查询将抓取几行 100k 行,然后使用 fParameters 将其过滤到那一周我需要的几百行。

我编写了一个新查询,以便获取更多需要的信息,问题是我正在使用 DECLARE 语句来设置这些开始/结束日期,并且在之后简单地过滤查询不再是一种选择。

这可能比我做的更容易,但是有什么方法可以简单地将单元格的值传递到我的查询中?

查询

DECLARE @StartDate DATE = '2020-10-25'
DECLARE @EndDate DATE = '2020-11-01'
DECLARE @Department VARCHAR(20) = 'Hotmill'
DECLARE @BonusCrew VARCHAR(100) = ''

    SET NOCOUNT ON;

DECLARE @StartDateTime DATETIME 
DECLARE @EndDateTime DATETIME 

BEGIN
    SET @StartDateTime = CAST(CAST(@StartDate AS VARCHAR) + ' 07:00' AS DATETIME)
    SET @EndDateTime = DATEADD(d,1,CAST(CAST(@EndDate AS VARCHAR) + ' 07:00' AS DATETIME))
END

DECLARE @tbl_crew table
    (
        crew varchar(1)
    )

    IF ISNULL(@BonusCrew,'') = ''
    BEGIN 
        --no crews, include everything
        INSERT INTO @tbl_crew VALUES ('A')
        INSERT INTO @tbl_crew VALUES ('B')
        INSERT INTO @tbl_crew VALUES ('C')
        INSERT INTO @tbl_crew VALUES ('D')
    END
    ELSE 
    BEGIN 
        declare @sql varchar(max)

        set @sql = 'select ltrim(param) from fn_MVParam(''' + @BonusCrew + ''', '','')'

        INSERT INTO @tbl_crew
        EXEC (@sql)
    END
    --Always include records with a missing crew designation
    INSERT INTO @tbl_crew VALUES ('')

SELECT DISTINCT
    CASE
        WHEN b.DefectCode = 'Chemistry out of range'        THEN 'CC'
        WHEN b.DefectCode = 'Chemistry transition'          THEN 'SCH'
        WHEN b.DefectCode = 'Comedown Bar'                  THEN 'SCH'
        WHEN b.DefectCode = 'Dimension - width over'        THEN 'SCH'
        WHEN b.DefectCode = 'Dimension - width over'        THEN 'SCH'
        WHEN b.DefectCode = 'Extra Steel'                   THEN 'SCH'
        WHEN b.DefectCode = 'First Bar'                     THEN 'SCH'
        WHEN b.DefectCode = 'Last Bar'                      THEN 'SCH'
        WHEN b.DefectCode = 'Melt/Cast - Lanced Open'       THEN 'CC'
        WHEN b.DefectCode = 'Surface - longitudinal crack'  THEN 'CC'
        WHEN b.DefectCode = 'Wrong Grade'                   THEN 'SCH'
        WHEN b.RespUnit = 'HRM1'                            THEN 'HM'
        ELSE b.RespUnit
    END AS 'Unit',
    b.matname 'Coil No.',
    b.weight / 2000.0 'Weight',
    b.Width,
    b.steelgradeid 'Grade',
    b.thickness 'Gauge',
    CASE 
        WHEN b.BonusType = 'Claim' THEN 'Claim'
        WHEN b.Disposition = 'SC' THEN 'SC'
        WHEN b.Disposition = 'HR' THEN '1B'
        WHEN b.Disposition = 'IS' THEN '2A'
        WHEN b.Disposition = 'EP' THEN '1X'
        WHEN b.Disposition = 'AD' THEN 'HA'
        ELSE '1A'
    END AS Disposition,
    hbcp.produced_dt_stamp 'HB Produciton Date',
    b.ProductionDate 'Production Date',
    b.AdjustmentDate 'Adjustment Date',
    CASE
        WHEN b.BonusType = 'Prime to EP'                            THEN 'Prime to 1X'
        WHEN b.BonusType = 'Prime to IS'                            THEN 'Prime to 2A'
        WHEN b.BonusType = 'Prime to AD'                            THEN 'Prime to HA'
        WHEN b.BonusType = 'Prime to HR'                            THEN 'Prime to 1B'
        WHEN b.BonusType = 'AD to IS'                               THEN 'HA to 2A'
        WHEN b.BonusType = 'AD to SC'                               THEN 'HA to SC'
        WHEN b.BonusType = 'EP to IS'                               THEN '1X to 2A'
        WHEN b.BonusType = 'AD to 1A within 7 days of production'   THEN 'HA to 1A within 7 days of production'
        WHEN b.BonusType = 'HR to 1A within 7 days of production'   THEN '1B to 1A within 7 days of production'
        WHEN b.BonusType = 'EP to 1A within 7 days of production'   THEN '1X to 1A within 7 days of production'
        WHEN b.BonusType = 'IS to 1A within 7 days of production'   THEN '2A to 1A within 7 days of production'
        ELSE b.BonusType
    END AS 'Bonus Type',
    CASE
        WHEN b.BonusType = 'claim'                                      THEN claim_reason.description
        WHEN b.DefectCode = 'Cobble - finishing mill'                   THEN 'Cobble'
        WHEN b.DefectCode = 'Cobble - coiler'                           THEN 'Cobble'
        WHEN b.DefectCode = 'Coil Package - collapsed coil'             THEN 'Coil Package'
        WHEN b.DefectCode = 'Coil Package - dished coil'                THEN 'Coil Package'
        WHEN b.DefectCode = 'Coil Package - folded edge'                THEN 'Coil Package'
        WHEN b.DefectCode = 'Coil Package - kinked ID'                  THEN 'Coil Package'
        WHEN b.DefectCode = 'Coil Package - loose wraps'                THEN 'Coil Package'
        WHEN b.DefectCode = 'Coil Package - oscillated'                 THEN 'Coil Package'
        WHEN b.DefectCode = 'Coil Package - telescoped coil'            THEN 'Coil Package'
        WHEN b.DefectCode = 'Coil Package - unfit to ship'              THEN 'Coil Package'
        WHEN b.DefectCode = 'Edges - damaged edges'                     THEN 'Edges'
        WHEN b.DefectCode = 'Edges - edge holes'                        THEN 'Edges'
        WHEN b.DefectCode = 'First Bar'                                 THEN 'First/Last Bar'
        WHEN b.DefectCode = 'Last Bar'                                  THEN 'First/Last Bar'
        WHEN b.DefectCode = 'Marks - bruises'                           THEN 'Marks'
        WHEN b.DefectCode = 'Marks - roll marks (other)'                THEN 'Marks'
        WHEN b.DefectCode = 'Melt/Cast - Lanced Open'                   THEN 'Lanced Open'
        WHEN b.DefectCode = 'Poor Physical Properties - CT variation'   THEN 'CT Variation'
        WHEN b.DefectCode = 'Scale - Held in Tunnel Furnace'            THEN 'Held in Tunnel Furnace'
        WHEN b.DefectCode = 'Scale - Pickled Out Streaks'               THEN 'Primary Scale'
        WHEN b.DefectCode = 'Scale - primary'                           THEN 'Primary Scale'
        WHEN b.DefectCode = 'Scale - Roll Wear/Roll Peel'               THEN 'Roll Peel'
        WHEN b.DefectCode = 'Scale - silicon streaks'                   THEN 'Primary Scale'
        WHEN b.DefectCode = 'Shape - center buckle'                     THEN 'Shape'
        WHEN b.DefectCode = 'Shape - edge wave'                         THEN 'Shape'
        WHEN b.DefectCode = 'Shape - quarter buckle'                    THEN 'Shape'
        WHEN b.DefectCode = 'Surface - laminations/holes'               THEN 'Lams/Holes'
        WHEN b.DefectCode = 'Surface - longitudinal crack'              THEN 'Longitudinal Cracks'
        WHEN b.DefectCode = 'Surface - nonmetallic inclusions'          THEN 'Inclusions'
        WHEN b.DefectCode = 'Surface - pits'                            THEN 'Pits'
        WHEN b.DefectCode IS NULL                                       THEN 'Reapplication'
        ELSE b.DefectCode
    END AS 'Defect',
    CASE
        WHEN b.BonusType = 'claim'  THEN claim_reason.description
        ELSE b.DefectCode 
    END AS 'Defect Description',
    b.REmark 'Remark',
    CASE b.REPORTINGUNIT
        WHEN 'B' THEN 'HRM1'
        WHEN 'P' THEN 'PL1'
        WHEN 'L' THEN 'PPPL'
        WHEN 'C' THEN 'TCM1'
        WHEN 'T' THEN 'TM1'
        WHEN 'A' THEN 'BAF'
        WHEN 'G' THEN 'CGL1'
        WHEN 'H' THEN 'CGL2'
        WHEN 'J' THEN 'CGL3'
        WHEN 'O' THEN 'OTHER'
    END AS REPORTINGUNIT,
    b.CREATEDBY,
    b.Crew,
    b.AdjustmentMultiplier 'Multiplier'

FROM 
    dbo.v_bonus_adjustment b
    INNER JOIN @tbl_crew c ON b.Crew = c.crew
    LEFT JOIN 
    (
        SELECT
            b.description,
            a.coil_no,
            a.claim_no,
            a.posted_date,
            a.controller_decision_date,
            claim.claim_close_date
        FROM
            dbo.coil_on_claim_credit a
            JOIN dbo.claim_reason b
                ON a.coil_credit_cd = b.claim_reason_cd
            JOIN claim
                ON a.claim_no=claim.claim_no
        WHERE 
            b.quality_approv_req = 'Y'
            AND a.coil_credit_cd NOT IN 
            (
                SELECT
                    claim_reason_cd
                FROM
                    dbo.claim_reason
                WHERE
                    bonus_related <> 'Y'
            )
            AND a.accepted_weight <> 0
            AND a.sequence_no = 
            (
                SELECT
                    MIN( sequence_no )
                FROM
                    dbo.coil_on_claim_credit c
                    JOIN dbo.claim_reason d
                        ON c.coil_credit_cd = d.claim_reason_cd
                WHERE
                    d.quality_approv_req = 'Y'
                    AND c.coil_credit_cd NOT IN
                    (
                        SELECT
                            claim_reason_cd
                        FROM
                            dbo.claim_reason
                        WHERE bonus_related <> 'Y'
                    )
                    AND c.coil_no = a.coil_no
                GROUP BY
                    c.coil_no
            )
    ) claim_reason
        ON b.matname = claim_reason.coil_no
        AND b.claim_no = claim_reason.claim_no
    LEFT JOIN all_produced_coils apc
        ON
        (
            b.production_coil_no = apc.production_coil_no
            OR claim_reason.coil_no = apc.production_coil_no
        )
    LEFT JOIN
    (
        SELECT
            production_coil_no,
            coil_defect_seq_no
        FROM
            regrade_history
        WHERE
            root_cd IS NOT NULL
            AND root_cd != 0
    ) AS rh
        ON apc.production_coil_no = rh.production_coil_no
    LEFT JOIN sdipdb.dbo.coil_defect cd
        ON rh.coil_defect_seq_no = cd.seq_no
    LEFT JOIN defect_root_cause rc
        ON cd.root_cd = rc.root_cd
    LEFT JOIN hb_coil_product_data hbcp
        ON hbcp.slab_no = apc.slab_no

WHERE
    ISNULL(claim_close_date, b.AdjustmentDate) >= @StartDateTime AND
    ISNULL(claim_close_date, b.AdjustmentDate) < @EndDateTime AND
    (
        (
            BonusType = 'Claim' AND RespUnit IN
            (
                SELECT 
                    ResponsibleUnit
                FROM dbo.bonus_departments
                WHERE 
                    Application = 'Claim'
                    AND Department = @Department
            )
        )
        OR
        (  
        RespUnit IN 
            (
                SELECT 
                    ResponsibleUnit
                FROM dbo.bonus_departments
                WHERE 
                    Application = 'Reject'
                    AND Department = @Department
            )
        )
    )

基本上,我只希望前 2 行中的那些日期用于声明开始和结束日期来自我在我的 excel 工作表中的 2 个单元格。 然后是我的查询和其他计算此表中的内容将一起更新。

【问题讨论】:

  • 这应该有助于展示如何在 Power Query 中获取单元格值:stackoverflow.com/questions/49281763
  • @AlexisOlson 那么我是否可以让 Start_Date = Excel ......[Name="Start_Date"]....如果我将单元格命名为 Start_Date?
  • 看起来不错。您使用您引用的范围的名称并从该范围中选择行和列以获得单个值(这是[Content]{0}[Column1] 部分)。
  • LET Start_Date = Excel.CurrentWorkbook(){[Name="Start_Date"]}[内容]{0}[Column1] End_Date = Excel.CurrentWorkbook(){[Name="End_Date"]} [内容]{0}[Column2] DECLARE (at)StartDate DATE = Start_Date DECLARE (at)EndDate DATE = End_Date @AlexisOlson 这样吗?
  • 您需要确保您没有尝试将它们作为字符串文字传递。见这里,例如:stackoverflow.com/questions/64882066

标签: sql excel parameter-passing powerquery


【解决方案1】:

在此工作后,调整代码部分步骤以包含所需过程 SQL 的其余部分,此示例的复杂性降低。

步骤:

  1. 新建 Excel 工作簿
  2. 用文本填充 Sheet1 A1:开始日期
  3. 用日期填充 Sheet1 B1:01/01/2022
  4. 选中 Sheet1 B1 后,单击工作表数据上方公式框左侧的名称范围框。在下一步之前它将包含 B1。
  5. 将名称范围框中的 B1 覆盖为以下内容,然后按 Enter:StartDate
  6. 用文本填充 Sheet1 A2:EndDate
  7. 用日期填充 Sheet1 B2:03/31/2022
  8. 选择 Sheet1 B2 后,单击工作表数据上方公式框左侧的名称范围框。在下一步之前它将包含 B2。
  9. 将名称范围框中的 B2 覆盖为以下内容,然后按 Enter:EndDate
  10. 此时您有一张包含 2 个标签和 2 个日期值的工作表,其中值字段引用为 2 个命名范围
  11. 单击数据功能区,从其他来源获取数据,空白查询
  12. 点击高级编辑器
  13. 删除高级编辑器中的内容
  14. 将以下内容粘贴到高级编辑器中,这将创建一个自定义函数,该函数将在主查询中用于传递命名范围(开始日期和结束日期)
(rangeName) =>
    Excel.CurrentWorkbook(){[Name=rangeName]}[Content]{0}[Column1]
  1. 点击完成
  2. 在查询属性的名称字段中填充以下值:GetValue
  3. 单击 Power Query 编辑器的关闭窗口 X。
  4. 出现提示时单击保留。
  5. 单击数据功能区,从其他来源获取数据,空白查询
  6. 点击高级编辑器,删除高级编辑器中的内容
  7. 将以下代码中的 2 个值替换为 XXX_YOUR_SERVER_NAME_XXX XXX_YOUR_DATABASE_NAME_XXX,然后将以下内容复制/粘贴到高级编辑器中:
let
    StartDateText= DateTime.ToText(GetValue("StartDate"),"yyyy-MM-dd"),
    EndDateText=   DateTime.ToText(GetValue("EndDate"),"yyyy-MM-dd"),
    Query_Stmt= 
    "DECLARE @StartDate DATE = '" & StartDateText & "'" &
    "#(lf)" &
    "DECLARE @EndDate DATE = '" & EndDateText & "'"  & 
    "#(lf)" &
    "DECLARE @Department VARCHAR(20) = 'Hotmill'
DECLARE @BonusCrew VARCHAR(100) = ''

SET NOCOUNT ON;
DECLARE @StartDateTime DATETIME 
DECLARE @EndDateTime DATETIME 
     
BEGIN
SET @StartDateTime = CAST(CAST(@StartDate AS VARCHAR) + ' 07:00' AS DATETIME)
SET @EndDateTime = DATEADD(d,1,CAST(CAST(@EndDate AS VARCHAR) + ' 07:00' AS DATETIME))
END
             
DECLARE @tbl_1 table (list_values varchar(1) )
DECLARE @tbl_2 table (datetime_value datetime )

BEGIN 
INSERT INTO @tbl_1 VALUES ('A')
INSERT INTO @tbl_1 VALUES ('B')
INSERT INTO @tbl_1 VALUES ('C')
INSERT INTO @tbl_1 VALUES ('D')
INSERT INTO @tbl_2 VALUES (GETDATE()-30)
INSERT INTO @tbl_2 VALUES (GETDATE()-60)
INSERT INTO @tbl_2 VALUES (GETDATE()-70)
INSERT INTO @tbl_2 VALUES (GETDATE()+10)
END
SELECT * from @tbl_1 a left join @tbl_2 b on 1=1"
     &
    //"where b.datetime_value >= " & StartDateText & " and b.datetime_value <= " & EndDateText & "",
    "where b.datetime_value >= @StartDateTime and b.datetime_value <= @EndDateTime",
    
    Source = Sql.Database("XXX_YOUR_SERVER_NAME_XXX", "XXX_YOUR_DATABASE_NAME_XXX", [Query=Query_Stmt])
in
    Source
    //To Confirm the Query and Date Variable Text, Comment our Source on the line above as //Source  and
    //uncomment the below line by removing the // prefix and click Done
    //StartDateText & "#(lf)" & EndDateText & "#(lf)" & Query_Stmt

请注意,在上面的代码中,以下代码调用了第一个查询中定义的函数,将 2 个命名范围(StartDate、EndDate)传递给在查询 1 中创建的自定义函数 GetValue:

    StartDateText= DateTime.ToText(GetValue("StartDate"),"yyyy-MM-dd"),
    EndDateText=   DateTime.ToText(GetValue("EndDate"),"yyyy-MM-dd"),
  1. 点击完成
  2. 单击 X 关闭 Power Query 编辑器窗口,出现提示时单击保留
  3. 响应任何有关权限/隐私的提示以执行查询。
  4. 更改第一张表上的日期并根据需要刷新查询表以查看结果

【讨论】:

    猜你喜欢
    • 2017-03-06
    • 1970-01-01
    • 2018-07-26
    • 1970-01-01
    • 1970-01-01
    • 2018-08-01
    • 2016-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多