您如何将其转换为 SQL Server 2008 语句?

-1 sql-server-2008 ms-access

我不确定如何将其从 Access 转换为 SQL。我们目前正在使用 SQL Server 2008。我正在尝试将 Access 报告迁移到 SQL 视图中。

SELECT 
  First(IIf(IsNull([dbo_CUST_ADDRESS]![STATE]),IIf(IsNull([dbo_CUSTOMER]![BILL_TO_STATE]),[dbo_CUSTOMER]![STATE],[dbo_CUSTOMER]![BILL_TO_STATE]),[dbo_CUST_ADDRESS]![STATE])) AS STATE
  , dbo_RECEIVABLE.INVOICE_ID
  , dbo_RECEIVABLE.INVOICE_DATE
  , dbo_RECEIVABLE.CUSTOMER_ID
  , First(IIf(IsNull([dbo_CUST_ADDRESS]![NAME]),IIf(IsNull([dbo_CUSTOMER]![BILL_TO_NAME]),[dbo_CUSTOMER]![NAME],[dbo_CUSTOMER]![BILL_TO_NAME]),[dbo_CUST_ADDRESS]![NAME])) AS COMPANY
  , Sum(IIf([dbo_RECEIVABLE_LINE]![GL_ACCOUNT_ID]='4005-008',0,[dbo_RECEIVABLE_LINE]![AMOUNT])) AS Inv_Total_Amt
  , Sum(IIf([dbo_RECEIVABLE_LINE]![REFERENCE]<>"LA-COUNTY" And [dbo_RECEIVABLE_LINE]![REFERENCE]<>"FREIGHT" And [dbo_RECEIVABLE_LINE]![GL_ACCOUNT_ID]<>'4005-008',[dbo_RECEIVABLE_LINE]![AMOUNT],0)) AS Subtotal
  , Sum(IIf([dbo_RECEIVABLE_LINE]![REFERENCE]="LA-COUNTY",[dbo_RECEIVABLE_LINE]![AMOUNT],0)) AS TAX
  , Sum(IIf([dbo_RECEIVABLE_LINE]![REFERENCE]="FREIGHT",[dbo_RECEIVABLE_LINE]![AMOUNT],0)) AS Freight
  , dbo_RECEIVABLE.SALESREP_ID    
FROM (((dbo_RECEIVABLE RIGHT JOIN dbo_RECEIVABLE_LINE ON dbo_RECEIVABLE.INVOICE_ID = dbo_RECEIVABLE_LINE.INVOICE_ID) LEFT JOIN dbo_CUSTOMER_ORDER ON dbo_RECEIVABLE_LINE.CUST_ORDER_ID = dbo_CUSTOMER_ORDER.ID) LEFT JOIN dbo_CUST_ADDRESS ON (dbo_CUSTOMER_ORDER.CUSTOMER_ID = dbo_CUST_ADDRESS.CUSTOMER_ID) AND (dbo_CUSTOMER_ORDER.SHIP_TO_ADDR_NO = dbo_CUST_ADDRESS.ADDR_NO)) LEFT JOIN dbo_CUSTOMER ON dbo_RECEIVABLE.CUSTOMER_ID = dbo_CUSTOMER.ID    
GROUP BY 
  dbo_RECEIVABLE.INVOICE_ID
  , dbo_RECEIVABLE.INVOICE_DATE
  , dbo_RECEIVABLE.CUSTOMER_ID
  , dbo_RECEIVABLE.SALESREP_ID    
ORDER BY 
  First(IIf(IsNull([dbo_CUST_ADDRESS]![STATE]),IIf(IsNull([dbo_CUSTOMER]![BILL_TO_STATE]),[dbo_CUSTOMER]![STATE],[dbo_CUSTOMER]![BILL_TO_STATE]),[dbo_CUST_ADDRESS]![STATE]))
  , dbo_RECEIVABLE.INVOICE_ID;
Run Code Online (Sandbox Code Playgroud)

这是我在 2015 年 10 月 21 日创建的内容。我更改了 WHERE 以查找发票编号以对其进行测试并添加嵌套 CASE。它显示了该发票的 2 行,并且没有将它们分组为 1。

选择
(SELECT TOP 1 CASE WHEN CUST_ADDRESS.STATE is NULL THEN CASE WHEN CUSTOMER.BILL_TO_STATE is NULL THEN CUSTOMER.STATE ELSE CUSTOMER.BILL_TO_STATE END ELSE CUST_ADDRESS.STATE END FROM dbo.RECEIVABLE RECEIVABLE ERIVEINABLE dbo.RECEIVABLE . dbo.RECEIVABLE_LINE.INVOICE_ID LEFT OUTER JOIN dbo.CUSTOMER_ORDER ON dbo.RECEIVABLE_LINE.CUST_ORDER_ID = dbo.CUSTOMER_ORDER.ID LEFT OUTER JOIN dbo.CUST_ADDRESS ON dbo.CUSTOMER.CUST_ORDER_Dbo.CUSTOMER.CUST_ORDER_ID = dbo.CUSTOMER.CUST_ORDER_Dbo.CUSTOMER. CUST_ADDRESS。ADDR_NO LEFT OUTER JOIN dbo.CUSTOMER ON dbo.RECEIVABLE.CUSTOMER_ID = dbo.CUSTOMER.ID WHERE dbo.RECEIVABLE.INVOICE_ID = 'iv184546') 作为状态, dbo.RECEIVABLE.RECINVOICE_ID,IVABLE_DBOICEDVOICE_ID. , dbo.RECEIVABLE.CUSTOMER_ID, (SELECT TOP 1 CASE WHEN dbo.CUST_ADDRESS.NAME 为 NULL THEN dbo.CUSTOMER.NAME ELSE dbo.CUST_ADDRESS.NAME END FROM dbo.RECEIVABLE RIGHT OUTER JOIN dbo.RECEIVABLEDLINE_VOIN dbo.RECEIVABLE_LINE.INVOICE_ID LEFT OUTER JOIN dbo.CUSTOMER_ORDER ON dbo.RECEIVABLE_LINE.CUST_ORDER_ID = dbo.CUSTOMER_ORDER。ID LEFT OUTER JOIN dbo.CUST_ADDRESS ON dbo.CUSTOMER_ORDER.CUSTOMER_ID = dbo.CUST_ADDRESS.CUSTOMER_ID AND dbo.CUSTOMER_ORDER.SHIP_TO_ADDR_NO = dbo.CUST_ADDRESS.RECADDR_NO LEFTINSTOMER_ORDER.CUSTOMER_ID = dbo.CUST_ADDRESS.CUSTOMER_ID dbo.RECEIVABLE.INVOICE_ID = 'iv184546') AS COMPANY, SUM(CASE WHEN RECEIVABLE_LINE.GL_ACCOUNT_ID = '4005-008' THEN 0 ELSE RECEIVABLE_LINE.AMOUNT END) AS Inv_Total_Amt, SUM-CASE WHEN CASE ' AND RECEIVABLE_LINE.REFERENCE <> 'FREIGHT' AND RECEIVABLE_LINE.GL_ACCOUNT_ID <> '4005-008' THEN RECEIVABLE_LINE.AMOUNT ELSE 0 END) 作为小计,SUM(CASE WHEN RECEIVABLE_LINE.REFERENCE = 'LA-COUNTY' THEN RECEIVABLE_LINE.AMOUNT ELSE 0 END)作为税款,SUM(CASE WHEN RECEIVABLE_LINE.REFERENCE = 'FREIGHT' THEN RECEIVABLE_LINE.AMOUNT ELSE 0 END。作为税款) SALESREP_ID

从 dbo.RECEIVABLE RIGHT OUTER JOIN dbo.RECEIVABLE_LINE ON dbo.RECEIVABLE.INVOICE_ID = dbo.RECEIVABLE_LINE.INVOICE_ID LEFT OUTER JOIN dbo.CUSTOMER_ORDER ON dbo.RECEIVABLE_LINEID.CUST_ORDERdbo.RECEIVABLE_LINEID.CUST_ORDERDBOFTA.CUST_ORDERdbo.RECEIVABLE_LINE.INVOICE_ID .CUSTOMER_ID = dbo.CUST_ADDRESS.CUSTOMER_ID AND dbo.CUSTOMER_ORDER.SHIP_TO_ADDR_NO = dbo.CUST_ADDRESS.ADDR_NO LEFT OUTER JOIN dbo.CUSTOMER ON dbo.RECEIVABLE.CUSTOMER_ID = .dboID6E4MER_ID=.dboID6E4MER_IDBOE4MER_4MERICUSTOMER_IDABLEIVECUID6 CUST_ADDRESS.STATE 为 NULL 时的情况 CUSTOMER.BILL_TO_STATE 为 NULL 时的情况则 CUSTOMER.STATE ELSE 客户。BILL_TO_STATE END ELSE CUST_ADDRESS.STATE END, dbo.CUSTOMER.NAME, dbo.RECEIVABLE.INVOICE_ID, dbo.RECEIVABLE.INVOICE_DATE, dbo.RECEIVABLE.POSTING_DATE, dbo.RECEIVABLE.CUSTOMER_SREIVABLEd.CUSTOM.INVOICE_ID, dbo.RECEIVABLE.INVOICE_DATE. NAME IS NULL THEN dbo.CUSTOMER.NAME ELSE dbo.CUST_ADDRESS.NAME END当 dbo.CUST_ADDRESS.NAME 为 NULL 时的情况,则 dbo.CUSTOMER.NAME ELSE dbo.CUST_ADDRESS.NAME END当 dbo.CUST_ADDRESS.NAME 为 NULL 时的情况,则 dbo.CUSTOMER.NAME ELSE dbo.CUST_ADDRESS.NAME END
ORDER BY dbo.RECEIVABLE.INVOICE_ID, dbo.RECEIVABLE.INVOICE_DATE;

ype*_*eᵀᴹ 8

而不是重写整个查询,我会给你一些关于如何做的提示:

  • IIf(condition, a, b) 变成: CASE WHEN condition THEN a ELSE b END
  • IsNull(x) 变成: x IS NULL
  • IIf(IsNull(x), y, x))然后可以将组合写为: CASE WHEN x IS NULL THEN y ELSE x END并进一步简化为COALESCE(x, y)
  • 表列表达式:[tab]![col]变为:[tab].[col]如果名称未保留,则更具可读性:tab.col
  • 对字符串文字使用单引号(而不是双引号)。例如,替换"FREIGHT"'FREIGHT'。双引号在标准 SQL(以及 SQL Server 中,除了括号之外)用于引用表和列的名称和别名,而不是用于文字。
  • FROM可以安全地删除子句中的括号。SQL Server 的解析器不管有没有它们都很满意。
  • 此外,如果您为表使用别名,可读性会增加:

    FROM (((dbo_RECEIVABLE RIGHT JOIN dbo_RECEIVABLE_LINE ON dbo_RECEIVABLE.INVOICE_ID = dbo_RECEIVABLE_LINE.INVOICE_ID) LEFT JOIN dbo_CUSTOMER_ORDER ON dbo_RECEIVABLE_LINE.CUST_ORDER_ID = dbo_CUSTOMER_ORDER.ID) LEFT JOIN dbo_CUST_ADDRESS ON (dbo_CUSTOMER_ORDER.CUSTOMER_ID = dbo_CUST_ADDRESS.CUSTOMER_ID) AND (dbo_CUSTOMER_ORDER.SHIP_TO_ADDR_NO = dbo_CUST_ADDRESS.ADDR_NO)) LEFT JOIN dbo_CUSTOMER ON dbo_RECEIVABLE.CUSTOMER_ID = dbo_CUSTOMER.ID 
    
    Run Code Online (Sandbox Code Playgroud)

    变成:

    FROM dbo_RECEIVABLE 
      RIGHT JOIN dbo_RECEIVABLE_LINE 
        ON  dbo_RECEIVABLE.INVOICE_ID = dbo_RECEIVABLE_LINE.INVOICE_ID
      LEFT JOIN dbo_CUSTOMER_ORDER 
        ON  dbo_RECEIVABLE_LINE.CUST_ORDER_ID = dbo_CUSTOMER_ORDER.ID
      LEFT JOIN dbo_CUST_ADDRESS 
        ON  dbo_CUSTOMER_ORDER.CUSTOMER_ID = dbo_CUST_ADDRESS.CUSTOMER_ID 
        AND dbo_CUSTOMER_ORDER.SHIP_TO_ADDR_NO = dbo_CUST_ADDRESS.ADDR_NO
      LEFT JOIN dbo_CUSTOMER 
        ON  dbo_RECEIVABLE.CUSTOMER_ID = dbo_CUSTOMER.ID 
    
    Run Code Online (Sandbox Code Playgroud)

    进而:

    FROM dbo_RECEIVABLE AS rec
      RIGHT JOIN dbo_RECEIVABLE_LINE AS line
        ON  rec.INVOICE_ID = line.INVOICE_ID
      LEFT JOIN dbo_CUSTOMER_ORDER AS ord
        ON  line.CUST_ORDER_ID = ord.ID
      LEFT JOIN dbo_CUST_ADDRESS AS addr
        ON  ord.CUSTOMER_ID = addr.CUSTOMER_ID 
        AND ord.SHIP_TO_ADDR_NO = addr.ADDR_NO
      LEFT JOIN dbo_CUSTOMER AS cust
        ON  rec.CUSTOMER_ID = cust.ID 
    
    Run Code Online (Sandbox Code Playgroud)

    相应地调整SELECT和中的所有引用GROUP BY

  • ORDER BY你可以使用包含或定义的列别名SELECT列表。无需重复复杂的表达式或表别名:

    ORDER BY STATE, INVOICE_ID; ; 
    
    Run Code Online (Sandbox Code Playgroud)
  • 顺便说RIGHT JOIN一下,这看起来不对。特别是因为GROUP BY是基于可为空的侧列(dbo_RECEIVABLE表)。它可能应该是INNERLEFT JOIN

  • First()功能是最困难的部分。你可以用MIN()or替换它,MAX()但你可能不会得到相同的结果,并且可能无法在所有查询中使用这个技巧,只有那些带有GROUP BY.
    等价物将非常复杂,使用其中之一ROW_NUMBER()并更改整个查询的结构(将其包装在派生表或 CTE 中并将其GROUP BY从内部级别移动到外部级别)。在 2012+ 版本中,FIRST_VALUE()也可能会使用该功能。