【问题标题】:How to use an Alias in a Calculation for Another Field如何在另一个字段的计算中使用别名
【发布时间】:2017-09-28 15:06:18
【问题描述】:

有人知道是否有办法复制this question 中使用的方法,即使用子查询的别名对 t-SQL 中的另一个字段执行计算?

我尝试在 MS SQL Express 中对以下查询使用相同的语法并得到以下错误:

DECLARE @PracticeID INT
DECLARE @Date1 date
DECLARE @Date2 date

SET @PracticeID = 11015
SET @Date1 = '2017-06-01'
SET @Date2 = '2017-09-01'

SELECT prtc.PracticeName ,COUNT(CASE WHEN udi.DevicePlatform = 'iOS' THEN 1 ELSE NULL END) iOSLogins,  
           COUNT(CASE WHEN udi.DevicePlatform = 'Android' THEN 1 ELSE NULL END) AndroidLogins,
          ( SELECT COUNT(*)
            FROM UserEvent UE
            WHERE UE.EventTypeID = 1 AND
                  UE.PracticeID = au.PracticeID AND
                  (UE.EventDate BETWEEN @Date1 and @Date2)
          ) TotalNumberLogins, 
          (SELECT TotalNumberofLogins) - ((SELECT iOSLogins) + (SELECT AndroidLogins )) DesktopLogins
    FROM UserDeviceInfo UDI JOIN
         AppUser AU ON udi.UserID = au.UserID JOIN
         Practice PRTC ON au.PracticeID = prtc.PracticeID 
    WHERE au.PracticeID = @PracticeID AND 
          (udi.Created BETWEEN @Date1 AND @Date2)
    GROUP BY prtc.PracticeName, au.PracticeID

消息 207,级别 16,状态 1,第 17 行无效的列名 “登录总数”。消息 207,级别 16,状态 1,第 17 行无效 列名“iOSLogins”。消息 207,级别 16,状态 1,第 17 行无效 列名“AndroidLogins”。

并不是说它会有所作为,但我确实尝试将别名放在引号和括号中,但无济于事。

我确实设法通过使用与变量相同的值而不是别名的值来执行计算,然后将它们插入到表中,从而从另一种方法中获得所需的结果。

但是,该查询很冗长,我想知道是否有任何方法可以复制引用问题中的行为以供将来使用。

感谢您提供的任何帮助。

【问题讨论】:

    标签: tsql subquery


    【解决方案1】:

    该方法在 SQL Server 中不起作用。您可以通过几种不同的方式完成同一件事:

    1.) 使用每个别名列的代码而不是别名:

    (SELECT COUNT(*)
     FROM UserEvent UE
     WHERE UE.EventTypeID = 1 
     AND UE.PracticeID = au.PracticeID 
     AND (UE.EventDate BETWEEN @Date1 and @Date2) 
    - COUNT(CASE WHEN udi.DevicePlatform = 'iOS' THEN 1 ELSE NULL END)
    + COUNT(CASE WHEN udi.DevicePlatform = 'Android' THEN 1 ELSE NULL END) Desktop Logics
    

    2.) 使用派生表制作列,然后您可以通过别名引用它们:

    SELECT PracticeName, iOSLogins, AndroidLogins, TotalNumberLogins,
           (TotalNumberofLogins - (iOSLogins + AndroidLogins)) DesktopLogins
    FROM (
           SELECT prtc.PracticeName,
                  COUNT(CASE WHEN udi.DevicePlatform = 'iOS' THEN 1 ELSE NULL END) iOSLogins,  
                  COUNT(CASE WHEN udi.DevicePlatform = 'Android' THEN 1 ELSE NULL END) AndroidLogins,
                 ( SELECT COUNT(*)
                   FROM UserEvent UE
                   WHERE UE.EventTypeID = 1 
                   AND UE.PracticeID = au.PracticeID 
                   AND (UE.EventDate BETWEEN @Date1 and @Date2)
                 ) TotalNumberLogins, 
           FROM UserDeviceInfo UDI 
           JOIN AppUser AU ON udi.UserID = au.UserID 
           JOIN Practice PRTC ON au.PracticeID = prtc.PracticeID 
           WHERE au.PracticeID = @PracticeID 
           AND (udi.Created BETWEEN @Date1 AND @Date2)
           GROUP BY prtc.PracticeName, au.PracticeID
        ) a --table alias
    

    编辑:表别名解释

    在一个简单的查询中:

    SELECT col1 FROM Table
    

    您知道col1 的表引用是Table。 (Table.Col1) 如果它是唯一的col1,则不必编写它,但您仍然知道它所引用的表。

    在一个简单的派生表中:

    SELECT col1 FROM (SELECT col1 FROM Table)
    

    inner 列的表引用仍然是Table,但是外部呢?在这种情况下,括号内的所有内容都是您的表,但在上面的示例中,该表未命名。 SQL Server 要求您为已创建的表命名/别名,以便您可以引用它:

    SELECT col1 FROM (SELECT col1 FROM Table) MyDerivedTable
    

    ...现在您有一个外部列的表引用:

    SELECT MyDerivedTable.col1 FROM (SELECT col1 FROM Table) MyDerivedTable
    

    一旦涉及更多表格,您也可以看到对此的更大需求:

    SELECT MyDerivedTable.col1
    FROM (SELECT col1 FROM Table) MyDerivedTable
    JOIN Table T on T.col1 = MyDerivedTable.col1
    

    编辑 2:CTE 选项:

    另一个选项是公用表表达式或 CTE:

    with cteName as (
    SELECT prtc.PracticeName,
           COUNT(CASE WHEN udi.DevicePlatform = 'iOS' THEN 1 ELSE NULL END) iOSLogins,  
           COUNT(CASE WHEN udi.DevicePlatform = 'Android' THEN 1 ELSE NULL END) AndroidLogins,
             ( SELECT COUNT(*)
               FROM UserEvent UE
               WHERE UE.EventTypeID = 1 
               AND UE.PracticeID = au.PracticeID 
               AND (UE.EventDate BETWEEN @Date1 and @Date2)
             ) TotalNumberLogins, 
       FROM UserDeviceInfo UDI 
       JOIN AppUser AU ON udi.UserID = au.UserID 
       JOIN Practice PRTC ON au.PracticeID = prtc.PracticeID 
       WHERE au.PracticeID = @PracticeID 
       AND (udi.Created BETWEEN @Date1 AND @Date2)
       GROUP BY prtc.PracticeName, au.PracticeID
    )
    
    SELECT PracticeName, iOSLogins, AndroidLogins, TotalNumberLogins,
           (TotalNumberofLogins - (iOSLogins + AndroidLogins)) DesktopLogins
    FROM cteName
    

    这些非常方便,因为它们在外部查询和内部查询之间创建了清晰的分隔。最终,它与内联派生表做同样的事情,所以选择对您来说更具可读性的版本。 (向 xorcus 建议添加 CTE 的道具)

    【讨论】:

    • 您的第二个建议正是我正在寻找的答案类型。非常感谢亚伦,你帮了大忙。附带说明一下,如果我删除了“a”表别名,为什么查询会失败?
    • @W.Harr 乐于助人。我在答案中添加了别名的解释,写评论太长了。简短的回答是您正在从结果集中创建一个伪表,而 SQL Server 要求您为表命名以便引用它。
    • 您可能会发现使用 WITH 比嵌套查询更具可读性:docs.microsoft.com/sql/t-sql/queries/…
    • @xorcus 好电话,我也添加了该选项 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 2022-12-11
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    相关资源
    最近更新 更多