【问题标题】:How to run a SQL query on an Excel table?如何在 Excel 表上运行 SQL 查询?
【发布时间】:2013-09-18 20:41:10
【问题描述】:

我正在尝试从另一个表中创建一个子表,该表包含按 A-Z 排序的所有姓氏字段,其中电话号码字段不为空。我可以用 SQL 很容易地做到这一点,但我不知道如何在 Excel 中运行 SQL 查询。我很想将数据导入 postgresql 并在那里查询,但这似乎有点过分。

对于我正在尝试做的事情,SQL 查询 SELECT lastname, firstname, phonenumber WHERE phonenumber IS NOT NULL ORDER BY lastname 可以解决问题。这似乎太简单了,因为它不是 Excel 本身无法做到的。如何在 Excel 中运行这样的 SQL 查询?

【问题讨论】:

标签: sql excel filtering


【解决方案1】:

有很多很好的方法可以完成这项工作,其他人已经提出了建议。跟着“通过 SQL 轨迹获取 Excel 数据”,这里有一些提示。

  1. Excel 具有“数据连接向导”,它允许您从另一个数据源或什至在同一个 Excel 文件中导入或链接。

  2. 作为 Microsoft Office(和操作系统)的一部分,有两个感兴趣的提供程序:旧的“Microsoft.Jet.OLEDB”和最新的“Microsoft.ACE.OLEDB”。在设置连接时查找它们(例如使用数据连接向导)。

  3. 一旦连接到 Excel 工作簿,工作表或区域就相当于表或视图。工作表的表名是工作表的名称,其后附加一个美元符号(“$”),并用方括号(“[”和“]”)括起来;范围,它只是范围的名称。要将未命名的单元格区域指定为记录源,请将标准 Excel 行/列表示法附加到方括号中工作表名称的末尾。

  4. 本机 SQL 将(或多或少)是 Microsoft Access 的 SQL。 (过去,它被称为 JET SQL;但 Access SQL 已经发展,我相信 JET 已被弃用。)

  5. 例如,阅读工作表:SELECT * FROM [Sheet1$]

  6. 例如,读取一个范围:SELECT * FROM MyRange

  7. 例如,读取未命名的单元格范围:SELECT * FROM [Sheet1$A1:B10]

  8. 有很多书籍和网站可以帮助您了解这些细节。

补充说明

默认情况下,假定 Excel 数据源的第一行包含可用作字段名称的列标题。如果不是这种情况,您必须关闭此设置,否则您的第一行数据“消失”以用作字段名称。这是通过将可选的HDR= setting 添加到连接字符串的扩展属性来完成的。默认为HDR=Yes,无需指定。如果没有列标题,需要指定HDR=No;提供商将您的字段命名为 F1、F2 等。

关于指定工作表的注意事项:提供程序假定您的数据表从指定工作表上最上端、最左边的非空白单元格开始。换句话说,您的数据表可以毫无问题地从第 3 行 C 列开始。但是,例如,您不能在单元格 A1 中的数据上方和左侧键入工作表标题。

关于指定范围的注意事项:当您将工作表指定为记录源时,如果空间允许,提供程序会在工作表中现有记录的下方添加新记录。当您指定一个范围(已命名或未命名)时,Jet 还会在空间允许的情况下在该范围内现有记录的下方添加新记录。但是,如果您重新查询原始范围,则结果记录集不包括范围之外新添加的记录。

CREATE TABLE: Short, Long, Single, Double, Currency, DateTime, Bit, Byte, GUID, BigBinary, LongBinary, VarBinary, LongText, VarChar, Decimal 的数据类型(值得尝试)。

连接到“旧技术”Excel(扩展名为 xls 的文件):Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\MyFolder\MyWorkbook.xls;Extended Properties=Excel 8.0;。对 Microsoft Excel 5.0 和 7.0 (95) 工作簿使用 Excel 5.0 源数据库类型,对 Microsoft Excel 8.0 (97)、9.0 (2000) 和 10.0 (2002) 工作簿使用 Excel 8.0 源数据库类型。

连接到“最新”的 Excel(文件扩展名为 xlsx 的文件):Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Excel2007file.xlsx;Extended Properties="Excel 12.0 Xml;HDR=YES;"

将数据视为文本:IMEX 设置将所有数据视为文本。 Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Excel2007file.xlsx;Extended Properties="Excel 12.0 Xml;HDR=YES;IMEX=1";

(更多详情http://www.connectionstrings.com/excel

更多信息请访问http://msdn.microsoft.com/en-US/library/ms141683(v=sql.90).aspxhttp://support.microsoft.com/kb/316934

通过 ADODB 通过 VBA 连接到 Excel,详细信息在 http://support.microsoft.com/kb/257819

http://support.microsoft.com/kb/275561 上的 Microsoft JET 4 详细信息

【讨论】:

  • 数据连接需要一个文件名,当任务是查询当前文件时,这是一个show-stopper。此外,查询不能像公式一样使用,您只能使用固定查询来填充范围;并且不会自动更新。 因此,它无法查询当前文件,也无法用作公式的直接替换。
  • @ivan_pozdeev 我刚刚使用 Excel 2010 为自己确认可以查询当前文件;我不知道更高版本的 Excel/Office 是否使这不再可能。我同意通过数据连接向导创建自引用表很笨拙 - 主要是因为连接是使用工作簿的完整路径建立的,因此重命名/复制/移动工作簿会导致破坏它或混淆结果。但是,对于使用 VBA 不成问题的工作簿,自引用查询非常易于管理。
  • @ivan_pozdeev 我也同意 Excel 没有针对自动刷新自引用表进行优化;假设始终是外部来源的数据。可以通过连接属性的使用选项卡进行自动刷新(如每隔几分钟重新加载),并且使用 VBA 可以利用重新计算事件。尽管如此,我不相信我曾经把它作为公式的替代品超卖。
  • “有很多很好的方法可以完成这项工作”——如果这没有掩盖所有这些“很好”的方法对于请求的用例实际存在的主要缺陷(哪些阻碍了它们的广泛使用),我不知道是什么。
  • 数据连接向导已从 Excel 365 中删除。:(
【解决方案2】:

tl;博士; Excel 原生完成所有这些 - 使用 filters 和或 tables

(http://office.microsoft.com/en-gb/excel-help/filter-data-in-an-excel-table-HA102840028.aspx)

您可以通过 oledb 连接以编程方式打开 excel,并对工作表中的表执行 SQL。

但是你可以做任何你要求做的事情,而无需公式,只需过滤器。

  1. 点击您正在查看的数据中的任意位置
  2. 转到功能区栏上的数据
  3. 选择“过滤器”它在中间,看起来像一个漏斗
    • 现在表格第一行中每个单元格的紧手侧都有箭头
  4. 点击电话号码上的箭头并取消选择空白(最后一个选项)
  5. 点击姓氏上的箭头并选择 a-z ordering(顶部选项)

玩一玩.. 一些注意事项:

  1. 您可以选择过滤后的行并将它们粘贴到其他位置
  2. 在左侧的状态栏中,您将看到总行数中有多少行符合您的过滤条件。 (例如,找到 313 条记录中的 308 条)
  3. 您可以在病房的 excel 2010 中按颜色进行过滤
  4. 有时我会创建计算列来提供状态或已清理的数据版本,然后您也可以按这些列进行过滤或排序。 (例如,像其他答案中的公式)

用过滤器来做,除非你要做很多,或者你想在某处或某处自动导入数据..但为了完整性:

一个 c# 选项:

 OleDbConnection ExcelFile = new OleDbConnection( String.Format( "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0;HDR=YES\"", filename));
 ExcelFile.Open();

一个方便的起点是查看架构,因为那里可能比您想象的要多:

List<String> excelSheets = new List<string>();

// Add the sheet name to the string array.
foreach (DataRow row in dt.Rows) {
    string temp = row["TABLE_NAME"].ToString();
    if (temp[temp.Length - 1] == '$') {
         excelSheets.Add(row["TABLE_NAME"].ToString());
    }
}

那么当你想查询一张表时:

 OleDbDataAdapter da = new OleDbDataAdapter("select * from [" + sheet + "]", ExcelFile);
 dt = new DataTable();
  da.Fill(dt);

注意 - 在 excel 中使用表格!:

Excel 具有“表格”功能,可以让数据表现得更像表格。这会给您带来一些巨大的好处,但不会让您执行所有类型的查询。

http://office.microsoft.com/en-gb/excel-help/overview-of-excel-tables-HA010048546.aspx

对于 excel 中的表格数据,这是我的默认设置。我要做的第一件事是单击数据,然后从功能区的主页部分选择“格式为表格”。这为您提供过滤和默认排序,并允许您按名称访问表和字段(例如 table[fieldname] )这还允许列上的聚合函数,例如最大值和平均值

【讨论】:

  • 如果您想减少列,我个人会将过滤后的行复制到新工作表并删除我不需要的列。你可以隐藏它们,但它很少值得。
  • using System.Data.OleDb; using System.Data;
  • 我每天过滤一次,使用 c# 每周访问几次电子表格。使用 c# 时,往往是将数据导入数据库以真正使用它..一旦数据在 sql server 中,实际查询其过滤器或 sql 并不值得在中级 sql 到 excel 级别执行。跨度>
【解决方案3】:

您可以按以下方式在本机执行此操作:

  1. 选择表格并使用 Excel 按姓氏对其进行排序
  2. 创建一个 2 行乘 1 列的高级筛选条件,例如 E1 和 E2,其中 E1 为空,E2 包含公式 =C6="" 其中 C6 是电话号码列的第一个数据单元格。
  3. 选择表并使用高级过滤器,复制到一个范围,使用 E1:E2 中的条件范围并指定要复制的位置 输出到

如果您想以编程方式执行此操作,我建议您使用宏记录器记录上述步骤并查看代码。

【讨论】:

  • 问题指定 SQL。
【解决方案4】:

我是否建议尝试一下QueryStorm - 这是一个 Excel 插件,可以非常方便地在 Excel 中使用 SQL。

此外,它是免费增值的。如果您不关心自动完成、错误曲线等,您可以免费使用它。只需下载并安装,即可在 Excel 中获得 SQL 支持。

免责声明:我是作者。

【讨论】:

  • 很遗憾,虽然它是一个很棒的工具,但它现在似乎只需要付费,除了 30 天的试用期。
  • 很遗憾,我投了这个票太快了,不会让我投反对票,确实有免费增值服务,但除非你有付费密钥,否则不会让你运行查询......现在卸载
  • @FlyingTurtle 您是否收到免费社区许可证的许可提示?如果是这样,那将是一个错误。如果是这样,请告诉我,我会调查一下。
【解决方案5】:

可以在 Excel 中使用 SQL。它只是隐藏得很好。 请参阅本教程:

http://smallbusiness.chron.com/use-sql-statements-ms-excel-41193.html

【讨论】:

  • 好像是在使用 SQL 来选择要导入 Excel 的数据,而不是针对当前电子表格运行查询?
  • 您只需要在 excel 中(在名称管理器中)为每个表创建一个名称,或者只需选择表并在显示单元格地址的框中输入名称。然后您可以使用它来查询工作表。在查询中,您获得了工作表的完整地址,因此如果您将电子表格移动到磁盘上的其他位置,查询将不起作用
【解决方案6】:

如果您需要执行此操作一次,只需按照 Charles 的说明进行操作,但也可以使用 Excel 公式和辅助列执行此操作,以防您希望使过滤器动态化。

假设您的数据位于工作表 DataSheet 上,并从以下列的第 2 行开始:

  • A:姓氏
  • B:名字
  • C:电话号码

此工作表上需要两个帮助列。

  • D2:=if(A2 = "", 1, 0),这是过滤列,对应你的where条件
  • E2:=if(D2 &lt;&gt; 1, "", sumifs(D$2:D$1048576, A$2:A$1048576, "&lt;"&amp;A2) + sumifs(D$2:D2, A$2:A2, A2)),这个对应order by

将这些公式复制到您的数据中。

在应该显示结果的工作表上创建以下列。

  • 答:第 2 行中以 1 开头的数字序列,这限制了您可以获得的总行数(有点像续集中的限制)
  • B2:=match(A2, DataSheet!$E$2:$E$1048576, 0),这是对应数据所在的行
  • C2:=iferror(index(DataSheet!A$2:A$1048576, $B2), ""),这是实际数据,如果没有数据则为空

复制B2和C2中的公式并将C列复制过去到D和E。

【讨论】:

    【解决方案7】:

    如果您使用 Expat 库编译了 GDAL/OGR,则可以使用 XLSX driver 读取 .xlsx 文件,并从命令提示符运行 SQL 表达式。例如,在电子表格所在目录下的 osgeo4w shell 中,使用 ogrinfo 实用程序:

    ogrinfo -dialect sqlite -sql "SELECT name, count(*) FROM sheet1 GROUP BY name" Book1.xlsx
    

    将对sheet1 运行SQLite 查询,并以不寻常的形式输出查询结果:

    INFO: Open of `Book1.xlsx'
          using driver `XLSX' successful.
    
    Layer name: SELECT
    Geometry: None
    Feature Count: 36
    Layer SRS WKT:
    (unknown)
    name: String (0.0)
    count(*): Integer (0.0)
    OGRFeature(SELECT):0
      name (String) = Red
      count(*) (Integer) = 849
    
    OGRFeature(SELECT):1
      name (String) = Green
      count(*) (Integer) = 265
    ...
    

    或者使用ogr2ogr 运行相同的查询来创建一个简单的CSV 文件:

    $ ogr2ogr -f CSV out.csv -dialect sqlite \
              -sql "SELECT name, count(*) FROM sheet1 GROUP BY name" Book1.xlsx
    
    $ cat out.csv
    name,count(*)
    Red,849
    Green,265
    ...
    

    要对较旧的 .xls 文件执行类似操作,您需要 XLS driver,它是针对 FreeXL 库构建的,这并不常见(例如,不是来自 OSGeo4w)。

    【讨论】:

      【解决方案8】:

      您可以在您选择的语言/平台中试用 Excel 的本机 DB 驱动程序。在 Java 世界中,您可以尝试使用http://code.google.com/p/sqlsheet/,它提供了用于直接处理 Excel 工作表的 JDBC 驱动程序。同样,您可以获得其他平台的 DB 技术的驱动程序。

      但是,我可以保证您很快就会遇到这些包装库提供的众多功能。更好的方法是使用 Apache HSSF/POI 或类似级别的库,但它需要更多的编码工作。

      【讨论】:

        【解决方案9】:

        我可能会误解我,但这不正是数据透视表的作用吗?您是否有表格中的数据或只是过滤列表中的数据?如果它不是表格,则将其设为一个(ctrl+l),然后只需激活表格中的任何单元格并在另一张工作表上插入数据透视表。然后将列姓氏、名字、电话号码添加到行部分。然后将电话号码添加到过滤器部分并过滤掉空值。现在正常排序。

        【讨论】:

          【解决方案10】:

          Microsoft Access 和 LibreOffice Base 可以将电子表格作为源打开并在其上运行 sql 查询。这将是运行各种查询的最简单方法,并且避免了运行宏或编写代码的混乱。

          Excel 还具有自动过滤器和数据排序功能,可以像您的示例一样完成许多简单的查询。如果您需要有关这些功能的帮助,Google 将是比我更好的教程来源。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-10-31
            • 2011-04-27
            • 1970-01-01
            • 1970-01-01
            • 2015-02-07
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多