Comment obtenir le nombre total de lignes d'un GROUPE PAR requête?
De l'AOP manuel:
PDOStatement::rowCount() retourne le
nombre de lignes affectées par la dernière
DELETE, INSERT ou UPDATE déclaration
exécuté par le correspondant
Objet PDOStatement.Si la dernière instruction SQL exécutée par
l'associé était un PDOStatement
SÉLECTIONNEZ déclaration, certaines bases de données
retourne le nombre de lignes retournées par
cette déclaration. Cependant, ce
le comportement est pas garantie pour tous les
les bases de données et ne doit pas être invoqué
pour les applications portables.
J'ai constaté que très récemment. J'avais juste changé ma db couche d'abstraction pour ne pas utiliser SELECT COUNT(1) ...
plus, parce que juste quering les lignes réelles et puis en comptant le résultat serait beaucoup plus efficace. Et maintenant AOP ne prend pas en charge le!?
Je n'utilise pas PDO pour MySQL et PgSQL, mais je le fais pour SQLite. Est-il un moyen (sans changer complètement le dbal retour) pour compter les lignes comme ceci en PDO? Dans MySQL, ce serait quelque chose comme ceci:
$q = $db->query('SELECT a, b, c FROM tbl WHERE oele = 2 GROUP BY boele');
$rows = $q->num_rows;
//and now use $q to get actual data
Avec la MySQLi et PgSQL pilotes, c'est possible. Avec tous les PDO, il n'est pas!?
PS. Au départ, ma solution a été d'étendre la SQLResult->count méthode (le mien) pour remplacer SELECT ... FROM
par SELECT COUNT(1) FROM
et juste retour de ce nombre (très inefficace, mais seulement pour SQLite AOP). Ce n'est pas assez bon, parce que dans l'exemple de requête ci-dessus est un GROUP BY
, qui changerait le sens de la COUNT(1)
.
- Ceci a me piquer dans le passé aussi, mais il a toujours été de cette façon — il n'a pas changé tout d'un coup. Postgres vous donnera le comte, MySQL ne sera pas. Vous êtes en supposant que l'exécution de l'interrogation et de compter les résultats seraient plus efficaces, mais que faire si vous avez 10s de milliers de lignes?
- MySQL vous donnera le comte. PHP est "native", SQLlite client aussi. Tout simplement pas PDO. Avec tous les pilotes.
- Si vous avez besoin d'une solution à l'extérieur de l'AOP (si ce n'est pas de suport countRows), vous pouvez essayer quelque chose comme: "select SUM(1) que le comte de ... ", je sais que ça fonctionne avec mySQL, il est juste d'ajouter de 1 pour chaque ligne retournée dans la requête (n'ai pas testé cela dans sqlLite), en fin de compte la valeur de count = count(*).
Vous devez vous connecter pour publier un commentaire.
Voici la solution pour vous
if($sth->fetch(PDO::FETCH_NUM) > 0)
a fonctionné pour moi. Merci!$sth->execute(array("key" => $key_value));
avec$key_value
une variable déclarée à l'avant de ce bloc.=
pas==
. stackoverflow.com/questions/12908502/mysql-double-equal-signCOUNT
int une requête avec unGROUP BY
en elle. Les résultats ne sont pas comme vous l'attendez. Ce qui n'était pas assez évident?C'est un peu la mémoire inefficace, mais si vous utilisez les données de toute façon, j'utilise fréquemment:
fetchAll()
plus tard. Mais, bien, vous l'avez déjà fait? Donc, vous pouvez pas utiliser le résultat de ce que, au lieu de chercher à nouveau? Elle peut exiger un peu de réécriture selon le code que vous utilisez.COUNT
int une requête avec unGROUP BY
en elle. Les résultats ne sont pas comme vous l'attendez. Ce qui n'était pas assez évident?La méthode que j'ai fini par utiliser est très simple:
Peut-être pas la plus efficace, mais il semble être infaillible, parce qu'elle compte l'original des résultats de la requête.
En conséquence à ce commentaire, l'SQLite problème a été introduite par une API changement dans 3.x.
Cela dit, vous pourriez vouloir examiner la manière dont AOP en fait implémente la fonctionnalité avant de l'utiliser.
Je ne suis pas familier avec son fonctionnement interne, mais je serais méfiant à l'idée que les AOP analyse de SQL (une erreur de syntaxe SQL apparaît dans la DB, journaux) laisser seul essaie de faire le moindre sens, afin de compter les lignes à l'aide d'une stratégie optimale.
En supposant qu'il n'a pas, en effet, des stratégies réalistes pour le retour d'un décompte de toutes les lignes dans une déclaration à la chaîne de la manipulation de la clause limit de votre instruction SQL, et soit de:
Une bien meilleure manière de compter, cependant, serait de exécuter entièrement optimisé requête qui permettra de le faire. Plus souvent que pas, cela signifie que la réécriture significative des morceaux de la requête initiale que vous essayez de paginer -- décapage inutiles champs et l'ordre des activités d'exploitation, etc.
Enfin, si vos ensembles de données sont assez gros pour compte toute sorte de décalage, vous pouvez également enquêter sur le retour de l'estimation calculée à partir de la statistiques au lieu de cela, et/ou périodiquement la mise en cache le résultat dans Memcache. À un certain point, ayant précisément correct compte n'est plus utile...
Garder à l'esprit qu'un
PDOStatement
estTraversable
. Étant donné une requête:Il peut être itéré:
Ou vous pouvez faire quelque chose comme ceci:
$query
est un objet) doit savoir combien de résultats.->valid
(en quelque sorte). Juste pour vérifier si un jeu de résultats est vide ou pas, avant de l'extraction de tous les objets. Vide ou n'est pas assez bon pour moi. C'est pas joli mais c'est efficace et ça fonctionne. Dans le cas où vous êtes intéressé: github.com/rudiedirkx/db_generic/commit/...Si vous êtes prêt à donner un indice de l'abstraction, alors vous pouvez utiliser une classe wrapper personnalisé qui passe tout simplement tout grâce à l'AOP. Dire quelque chose comme ceci: (Attention, le code non testé)
Database
de classe et d'adaptateurs spécifiques commeMySQL
,SQLite
,PDOSQLite
et spécifique des jeux de résultats commeMySQLResult
,SQLiteResult
,PDOResult
. Je pouvais modifier le PDOResult classe entièrement sans modifier les fonctionnalités des applications ou des appels (, mais je préfère pas).Peut-être que cela va faire l'affaire pour vous?
no such function: FOUND_ROWS
FOUND_ROWS
n'apparaît pas dans la liste de leurs fonctions. Car il n'est pas disponible dans la base de données, il semble que vous devez utilisercount(*)
Source. C'est à partir de SQLite, pas PDO.count
ne font pas la même chose... Voir mon exemple dans la question: si il y a unGROUP BY
,COUNT
"signifie" quelque chose d'autre.FOUND_ROWS()
est pour MySQL, SQLite n'est pas une option similaire. Cependant, pour MySQL c'est certainement la bonne réponse.Vous devez utiliser rowCount — Retourne le nombre de lignes affectées par la dernière instruction SQL
Ce sujet de mettre les résultats de la requête dans un tableau, où vous pouvez faire un count($array) et utiliser la requête lignes obtenues après? Exemple:
C'est encore une autre question, qui, à tort mettre, engendre BEAUCOUP de terrible solutions, tout en rendant les choses terriblement compliqué à résoudre inexistante de problème.
Extrêmement simple et évidente de la règle pour toute base de données d'interaction est
Toujours sélectionner les seules données dont vous avez besoin.
De ce point de vue, la question est mal et l'on a accepté la réponse est juste. Mais d'autres solutions proposées sont tout simplement terrible.
La question est "comment obtenir le comte mauvais sens". On ne devrait jamais de réponse, il est aisé, mais au lieu de cela, la seule bonne réponse est "On ne devrait jamais sélectionner les lignes à les compter. Au lieu de cela, demandez TOUJOURS à la base de données à compter le nombre de lignes pour vous." Cette règle est tellement évident, que c'est juste improbable de voir autant essaie de le casser.
Après l'apprentissage de cette règle, on verrait que c'est un SQL question, pas même AOP liés. Et, s'il en avait demandé correctement, à partir de SQL point de vue, la réponse serait apparu dans un instant -
DISTINCT
.est la bonne réponse à cette question particulière.
L'ouverture de l'affiche de solution propre est également acceptable du point de vue de la disposition précitée, mais elle serait moins efficace en termes généraux.
Il y a deux façons vous pouvez compter le nombre de lignes.
Ou deuxième façon est