【问题标题】:SQL NOOB - nested/subqueiresSQL NOOB - 嵌套/子查询
【发布时间】:2018-10-12 15:27:59
【问题描述】:

我将首先明确说明我不是程序员,我本质上是一名会计师!

我需要将与在给定周内有交易的工作相关的所有交易返回到 Excel 中(即,以便我可以看到一周内的金额和迄今为止的总金额)。

我相当精通 excel 中的 VBA(无论如何都要像会计师一样!),但我一直只是复制并使用相同的旧 SQL 语句。本质上,我认为我需要做的是一个子查询来代替以下 WHERE 语句的订单号:

    With Sheet1.QueryTables.Add(Connection:=Array(Array( _
            "ODBC;DRIVER={iSeries Access ODBC Driver};SYSTEM=JADE;DBQ=QGPL LIVDTALIB;DFTPKGLIB=QGPL;LANGUAGEID=ENU;PKG=QGPL/DEFAULT(IBM),2,0,1,0,"), _
            Array("512;QRYSTGLMT=-1;")), Destination:=Sheet1.Range("A1"))
            .CommandText = Array( _
            "SELECT SLBGDTPF.BGMCU, SLBGDTPF.BGDSDT, SLBGDTPF.ORTYPE, SLBGDTPF.ORDNO, SLBGDTPF.BGDSVL, SLBGDTPF.BGCD, ", _
            "SLBGDTPF.ADBBG, SLBGDTPF.BGRMK" _
            & Chr(13) & "" & Chr(10) & _
            "FROM RCHASE5C.LIVDTALIB.SLBGDTPF SLBGDTPF" _
            & Chr(13) & "" & Chr(10) & _
            "WHERE (SLBGDTPF.ORDNO='30214884')")
        .Name = "TEST Query"
        .FieldNames = True
        .RefreshStyle = xlOverwriteCells
        .Refresh BackgroundQuery:=False
    End With

作为一个独立的查询,子查询元素的样子如下:

    With Sheet2.QueryTables.Add(Connection:=Array(Array( _
            "ODBC;DRIVER={iSeries Access ODBC Driver};SYSTEM=JADE;DBQ=QGPL LIVDTALIB;DFTPKGLIB=QGPL;LANGUAGEID=ENU;PKG=QGPL/DEFAULT(IBM),2,0,1,0,"), _
            Array("512;QRYSTGLMT=-1;")), Destination:=Sheet2.Range("A1"))
            .CommandText = Array( _
            "SELECT SLBGDTPF.ORDNO" _
            & Chr(13) & "" & Chr(10) & _
            "FROM RCHASE5C.LIVDTALIB.SLBGDTPF SLBGDTPF" _
            & Chr(13) & "" & Chr(10) & _
            "WHERE SLBGDTPF.BGPSDT='20180420'" _
            & Chr(13) & "" & Chr(10) & _
            "GROUP BY SLBGDTPF.ORDNO")
        .Name = "TEST Query"
        .FieldNames = True
        .RefreshStyle = xlOverwriteCells
        .Refresh BackgroundQuery:=False
    End With

我愿意接受所有建议,包括替代方法(我确实尝试使用 IN 并在工作表中引用一个范围,但我需要传递多达 1,000 个不同的工作编号)

仅供参考,这是一个模板,将发送给企业内的人员进行自我更新,因此需要建立连接,而不仅仅是让他们刷新工作簿中的现有查询。

一切顺利,

【问题讨论】:

  • 没有人在内心深处是个会计师,只能靠说服力。
  • 更具建设性的是,您为什么不能使用数据透视表?
  • 您是否有示例说明您的源数据是什么样的以及您的预期返回值是什么样的?
  • 在您的 WHERE 子句中,您有 WHERE SLBGDTPF.BGPSDT='20180420',它应该只为您提供 4 月 20 日的交易。如果您想要一整周,如果我理解正确,您将需要执行类似 WHERE SLBGDTPF.BGPSDT>='20180420' AND SLBGDTPF.BGPSDT<'20180428' 的操作。您可能希望为此输入使用 Excel 工作表上的一个字段(虽然代码有点多,但它可以避免您每次都修改查询)。
  • 不需要这行:& Chr(13) & "" & Chr(10) & _。在上面和/或下面的行中,只需在 FROMWHEREGROUP BY 之前在带引号的字符串中包含一个额外的空格作为分隔符。

标签: sql excel vba subquery odbc


【解决方案1】:

这可以通过几种方式实现,但假设数据库可以处理子查询,我会尝试使用 WHERE IN 术语。为了清楚起见,我还进行了一些其他粗略的编辑。最终的 GROUP BY 术语在子查询中是多余的,因为只有一个子查询 SELECT 字段并且没有进行聚合。

With Sheet1.QueryTables.Add(Connection:=Array(Array( _
        "ODBC;DRIVER={iSeries Access ODBC Driver};SYSTEM=JADE;DBQ=QGPL LIVDTALIB;DFTPKGLIB=QGPL;LANGUAGEID=ENU;PKG=QGPL/DEFAULT(IBM),2,0,1,0,"), _
        Array("512;QRYSTGLMT=-1;")), Destination:=Sheet1.Range("A1"))
        .CommandText = Array( _
        "SELECT SLBGDTPF.BGMCU, SLBGDTPF.BGDSDT, SLBGDTPF.ORTYPE, SLBGDTPF.ORDNO, SLBGDTPF.BGDSVL, SLBGDTPF.BGCD, SLBGDTPF.ADBBG, SLBGDTPF.BGRMK" & vbCrLf & _
        "FROM RCHASE5C.LIVDTALIB.SLBGDTPF SLBGDTPF" & vbCrLf & _
        "WHERE SLBGDTPF.ORDNO IN (" & vbCrLf & _
            "SELECT SLBGDTPF.ORDNO" & vbCrLf & _
            "FROM RCHASE5C.LIVDTALIB.SLBGDTPF SLBGDTPF" & vbCrLf & _
            "WHERE SLBGDTPF.BGPSDT='20180420')")
    .Name = "TEST Query"
    .FieldNames = True
    .RefreshStyle = xlOverwriteCells
    .Refresh BackgroundQuery:=False
End With

【讨论】:

    【解决方案2】:

    正如@IanPeters 已经提到的,有几种方法可以在 SQL 中处理这个问题。我想添加两个使用连接而不是 WHERE 子句之一的版本。 您可能想要测试哪个版本在您的数据库上表现最好。这将取决于数据库上的索引结构以及查询优化器处理查询的能力。

    连接中的子查询:

    With Sheet1.QueryTables.Add(Connection:=Array(Array( _
            "ODBC;DRIVER={iSeries Access ODBC Driver};SYSTEM=JADE;DBQ=QGPL LIVDTALIB;DFTPKGLIB=QGPL;LANGUAGEID=ENU;PKG=QGPL/DEFAULT(IBM),2,0,1,0,"), _
            Array("512;QRYSTGLMT=-1;")), Destination:=Sheet1.Range("A1"))
        .CommandText = Array( _
            "SELECT SLBGDTPF.BGMCU, SLBGDTPF.BGDSDT, SLBGDTPF.ORTYPE, SLBGDTPF.ORDNO, SLBGDTPF.BGDSVL, SLBGDTPF.BGCD, SLBGDTPF.ADBBG, SLBGDTPF.BGRMK" & vbCrLf & _
            "FROM RCHASE5C.LIVDTALIB.SLBGDTPF SLBGDTPF" & vbCrLf & _
                "INNER JOIN" & vbCrLf & _   
                    "(SELECT S.ORDNO" & vbCrLf & _
                    "FROM RCHASE5C.LIVDTALIB.SLBGDTPF S" & vbCrLf & _
                    "WHERE WeekOrders.BGPSDT='20180420') WeekOrders" & vbCrLf & _
                "ON SLBGDTPF.ORDNO = WeekOrders.ORDNO") 
        .Name = "TEST Query"
        .FieldNames = True
        .RefreshStyle = xlOverwriteCells
        .Refresh BackgroundQuery:=False
    End With
    

    连接之外的条件:

    With Sheet1.QueryTables.Add(Connection:=Array(Array( _
            "ODBC;DRIVER={iSeries Access ODBC Driver};SYSTEM=JADE;DBQ=QGPL LIVDTALIB;DFTPKGLIB=QGPL;LANGUAGEID=ENU;PKG=QGPL/DEFAULT(IBM),2,0,1,0,"), _
            Array("512;QRYSTGLMT=-1;")), Destination:=Sheet1.Range("A1"))
        .CommandText = Array( _
            "SELECT SLBGDTPF.BGMCU, SLBGDTPF.BGDSDT, SLBGDTPF.ORTYPE, SLBGDTPF.ORDNO, SLBGDTPF.BGDSVL, SLBGDTPF.BGCD, SLBGDTPF.ADBBG, SLBGDTPF.BGRMK" & vbCrLf & _
            "FROM RCHASE5C.LIVDTALIB.SLBGDTPF SLBGDTPF" & vbCrLf & _
                "INNER JOIN RCHASE5C.LIVDTALIB.SLBGDTPF WeekOrders" & vbCrLf & _
                    "ON SLBGDTPF.ORDNO = WeekOrders.ORDNO" & vbCrLf & _
            "WHERE WeekOrders.BGPSDT='20180420'") 
        .Name = "TEST Query"
        .FieldNames = True
        .RefreshStyle = xlOverwriteCells
        .Refresh BackgroundQuery:=False
    End With
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多