使用PDO有效地获取带有WHERE子句的SELECT查询返回的行数(Efficiently getting number of rows returned of SELECT query with WHERE clause using PDO)
关于如何在使用PDO运行
SELECT
查询时获取返回的行数,有很多关于SO的讨论 。 虽然大多数(包括PHP手册 )建议使用两个查询,第一个运行COUNT()
,但我没有看到一个建议如何使用带有WHERE
子句的预处理语句轻松完成此操作。我如何最有效地(在处理和代码行数中
COUNT()
使用相同的WHERE
子句运行COUNT()
? 准备好的查询已经指定了列。fetchAll()
在这里不起作用,因为它不会缩放; 如果我必须返回数百万行,使用fetchAll处理它将会非常慢。例如,没有计数:
$sql = "SELECT FirstName, LastName FROM People WHERE LastName = :lastName"; $query = $pdoLink->prepare($sql); $query->bindValue(":lastName", '%Smith%'); $query->execute(); while($row = $query->fetch(PDO::FETCH_ASSOC)) { echo $row['FirstName'] . " " . $row['LastName']; }
我看着只是向
SELECT
子句添加COUNT(ID)
,并让它只是一个查询,但看起来没有真正的好方法(或者不是特定于数据库的方式fetch()
一旦我得到一个倒带fetch()
从它排。另一个解决方案可能是使
WHERE
子句成为自己构建的变量。 但是,这似乎不是很有效。 它正在准备两个查询,重新绑定值并执行它。所以类似于:
$whereClause = " WHERE LastName = :lastName"; $rowsSql = "SELECT COUNT(ID) As NumOfRows FROM People " . $whereClause; $rowsQuery = $pdoLink->prepare($sql); $rowsQuery->bindValue(":lastName", '%Smith%'); $rowsQuery->execute(); if ($rowsQuery->fetchColumn() >= 1) //Prepare the original query, bind it, and execute it. $sql = "SELECT FirstName, LastName FROM People " . $whereClause; $query = $pdoLink->prepare($sql); $query->bindValue(":lastName", '%Smith%'); $query->execute(); while($row = $query->fetch(PDO::FETCH_ASSOC)) { echo $row['FirstName'] . " " . $row['LastName']; } } else { //No rows found, display message echo "No people found with that name."; }
There are numerous discussions on SO regarding how to get the number of rows returned when running a
SELECT
query using PDO. While most (including the PHP manual) suggest using two queries, with the first runningCOUNT()
, I haven't seen one that suggested how to easily do this using prepared statements withWHERE
clauses.How do I most-efficiently (both in processing and number of lines of code) run a
COUNT()
using the sameWHERE
clause? The prepared query already has the columns specified.fetchAll()
won't work here because that won't scale; if I have to return millions of rows, processing it using fetchAll would be super slow.For example, without the count:
$sql = "SELECT FirstName, LastName FROM People WHERE LastName = :lastName"; $query = $pdoLink->prepare($sql); $query->bindValue(":lastName", '%Smith%'); $query->execute(); while($row = $query->fetch(PDO::FETCH_ASSOC)) { echo $row['FirstName'] . " " . $row['LastName']; }
I looked at just adding
COUNT(ID)
to theSELECT
clause, and having it be just one query, but it looks like there is no real good way (or not database-specific way) of rewinding thefetch()
once I get a row from it.Another solution could be making the
WHERE
clause it's own variable that is built. But, that doesn't seem very efficient. It's preparing two queries, binding the values all over again, and executing it.So something like:
$whereClause = " WHERE LastName = :lastName"; $rowsSql = "SELECT COUNT(ID) As NumOfRows FROM People " . $whereClause; $rowsQuery = $pdoLink->prepare($sql); $rowsQuery->bindValue(":lastName", '%Smith%'); $rowsQuery->execute(); if ($rowsQuery->fetchColumn() >= 1) //Prepare the original query, bind it, and execute it. $sql = "SELECT FirstName, LastName FROM People " . $whereClause; $query = $pdoLink->prepare($sql); $query->bindValue(":lastName", '%Smith%'); $query->execute(); while($row = $query->fetch(PDO::FETCH_ASSOC)) { echo $row['FirstName'] . " " . $row['LastName']; } } else { //No rows found, display message echo "No people found with that name."; }
原文:https://stackoverflow.com/questions/15887692
最满意答案
更换:
for i in range(1, 31):
有:
for d in Data[1:31]: #since you have range(1,31). Do Data[1:] if you just want to skip the first OneDate.append(d[0]) OneClose.append(d[4])
当
Data
数组少于31个索引时,通常会发生这种情况。 同时确保d
数组至少有5个项目,否则d[4]
也会产生类似的错误。 使用:if len(d) >= 5: #check first. OneDate.append(d[0]) OneClose.append(d[4])
Replace:
for i in range(1, 31):
with:
for d in Data[1:31]: #since you have range(1,31). Do Data[1:] if you just want to skip the first OneDate.append(d[0]) OneClose.append(d[4])
This usually happends when
Data
array has less than 31 indices. Also ensured
array has atleast 5 items, elsed[4]
will also throw a similar error. Use:if len(d) >= 5: #check first. OneDate.append(d[0]) OneClose.append(d[4])
相关问答
更多-
你的一条线(可能是你的最后一条)不是你期望的格式。 在你的内部for循环中执行此操作: A=line.split(' ') if len(A) > 1: print A[1] One of your lines (probably your last) is not in the format you expect. Do this in your inner for loop: A=line.split(' ') if len(A) > 1: print A[1]
-
获取IndexError:列表赋值索引在python中超出范围(Getting IndexError: list assignment index out of range in python)[2022-03-06]
索引超出范围,因为如果从原始数组中删除项目,则原始数组的大小会减小。 尝试使用pop()删除最后一项 arr = ['A', 't', 'u', 'l', '%20', 'K', 'r', 'i', 's', 'h', 'n', 'a', '%20', 'P', 'a', 't', 'n', 'a', '%20', 'B', 'i', 'h', 'a', 'r', '%20', 'I', 'n', 'd', 'i', 'a', '%20', '%20', '%20', '%20', '%20'] lengt ... -
IndexError:使用列表在Python中列出索引超出范围(IndexError: list index out of range in Python using lists)[2023-07-12]
你使用的是不好的范围 number3 = 10 number10 = 10 -1 = 9 test = range(1,9) # 1,2,3,4,5,6,7,8 #notice how many variables there are if 9 < number3: test[9] # error you are using a bad range number3 = 10 number10 = 10 -1 = 9 test = range(1,9) # 1,2,3,4,5,6,7,8 #noti ... -
至少其中一个room.x1 + 1 , room.x2 , room.y1 + 1和room.y2超出了你的地图。 检查地图大小或限制访问权限。 选项1: class RoomOutsideError(Exception): pass # ... def create_room(room): global map #set all tiles inside the room to passable # check for limits and raise excepti ...
-
您的安装似乎有些问题 - 很难看出线路如何 while logger: 会生成一个IndexError 。 因此,从系统中删除所有.pyc和.pyo文件(包括在stdlib文件夹中),然后重试。 确保您的模块没有与标准库中的任何模块同名。 另外,您使用的是哪个版本的Python,以及在哪个平台上? 更新:如果您在C ++程序中使用嵌入式或使用C扩展,很可能某些C或C ++代码会破坏内存,从而导致IndexError在意外的地方。 你能在纯Python环境中重现吗? 如果没有,我担心问题可能出在C / C ...
-
Python / Pygame - IndexError:列表索引超出范围(Python/Pygame - IndexError: list index out of range)[2022-08-31]
由于range(0, nbpixel, cellsize) is [0, 20, 40, 60, ..., 400]并且你想检查coordinates [x][y]然后设置range(0, nbpixel/cellsize)那样你将处理每个单元格索引。 bouttonbomb = pygame.image.load("bouttonbomb.jpg").convert() maxindex = nbpixel/cellsize for x in range(0, maxindex): ... -
你在range (0, len(chests))进行迭代range (0, len(chests)) ,然后在线路visits[i] += 1中得到错误。 看起来像chests和visits长度不等。 我看不到任何appends到visits列表,所以它基本上是空的。 此外,您正在混合嵌套循环中的计数器: for i in range (0, len(chests)): ... # you override the i value here for i in range(0, len ...
-
你缺少的是range(1, maxIter)而不是(1,maxIter,1) 。 所以你会有 yvalue = [iniPop] for i in range(1, maxIter): yvalue.append(yvalue[i - 1] * (1 + (rate * (1 - (yvalue[i - 1] / CC))))) What you're missing is range(1, maxIter) instead of just (1,maxIter,1). So you'll hav ...
-
很高兴看到一些聪明的蔬菜编程。 首先,你的问题。 就像@Vasiliy所说,你有3个指数。 n ,因为你可以用你的条件来保护它。 1很好,因为enumerate总是生成2件事。 那只是留下了m 。 这是你的问题。 假设你在strlist有N元素。 对于strlist每个元素e ,您可以对其应用split() 。 e.split()的元素数量并不总是等于N m守时条件是针对N而不是len(e.split()) ,因此指数超出范围。 要解决此问题,请首先拆分字符串,然后循环遍历它。 当你在它的时候,不妨完全摆脱 ...
-
actual_ans_dict是一个空列表。 您正在尝试将值设置为actual_ans_dict[data[0]]但不存在具有此索引的元素。 您可以将actual_ans_dict的类型actual_ans_dict为dict : actual_ans_dict = {} for data in prsnobj.result: actual_ans_dict[data[0]] = data[1] print actual_ans_dict actual_ans_dict is an emp ...