To display my results from PDO, I always use following PHP code for example:
$STH = $DBH->prepare("SELECT logo_id, guess_count, guessed, count(id) AS counter FROM guess WHERE user_id=:id");
$STH->bindParam(":id",$loginuser['id']);
$STH->execute();
while($row = $STH->fetch()){
print_r($row);
}
Now the issue is that I only get one result. I used to use $STH->rowCount() to check the amount of rows returned, but this method isn't really advised for SELECT statements because in some databases it doesn't react correctly. So I used the count(id) AS counter, but now I only get one result every time, even though the value of $row['counter'] is larger than one.
What is the correct way to count the amount of results in one query?
If you want to check the number of rows that are returned by a query, there are a couple of options.
You could do a ->fetchAll to get an array of all rows. (This isn't advisable for large result sets (i.e. a lot of rows returned by the query); you could add a LIMIT clause on your query to avoid returning more than a certain number of rows, if what you are checking is whether you get more than one row back, you would only need to retrieve two rows.) Checking the length of the array is trivial.
Another option is to run a another, separate query, to get the count separately, e.g.
SELECT COUNT(1) AS counter FROM guess WHERE user_id=:id
But, that approach requires another round trip to the database.
And the old standby SQL_CALC_ROUND_ROWS is another option, though that too can have problematic performance with large sets.
You could also just add a loop counter in your existing code:
$i = 0;
while($row = $STH->fetch()){
$i++
print_r($row);
}
print "fetched row count: ".$i;
If what you need is an exact count of the number of rows that satisfy a particular predicate PRIOR to running a query to return the rows, then the separate COUNT(1) query is likely the most suitable approach. Yes, it's extra code in your app; I recommend you preface the code with a comment that indicates the purpose of the code... to get an exact count of rows that satisfy a set of predicates, prior to running a query that will retrieve the rows.
If I had to process the rows anyway, and adding LIMIT 0,100 to the query was acceptable, I would go for the ->fetchAll(), get the count from the length of the array, and process the rows from the array.
You have to use GROUP BY. Your query should look like
SELECT logo_id, guess_count, guessed, COUNT(id) AS counter
FROM guess
WHERE user_id=:id
GROUP BY logo_id, guess_count, guessed
Related
I've just had to start paging in SQL Server 2012 and I'm trying to get the total row count before paging is applied, but the problem I have is that my view has a few too many function calls in it that massively slow it down.
I've looked at this post and I've ended up with a query that takes 39 secs to run without the full data set in the DB.
Get total row count while paging
SELECT *
, COUNT(TaskId) OVER()
FROM TaskVersionView
WHERE (.. ~10 predicates here .. )
ORDER BY StartDate
OFFSET 0 ROWS
FETCH NEXT 50 ROWS ONLY
Without the COUNT it takes <1 second.
I would have expected SQL to optimize it so that it only counts the TaskIds instead of calling the functions but that doesn't seem to be the case, because:
SELECT COUNT(TaskId)
FROM TaskVersionView
Takes <1 sec.
I would have expected SQL to optimize it so that it only counts the TaskIds instead of calling the functions
If the predicates are always 'true' then this 'optimization' would return the correct value. Not that SQL Server could, even in theory, guess that the functions will always return true. But if you know (as it seems to imply from your expectation) that the functions in the predicates always return true then obviously you should remove them from the WHERE clause...
If the predicates sometimes return 'false' then obviously they cannot be optimized away, as the returned values would be incorrect.
Something gotta give.
PS. Paging with total counts is a bad idea, as it forces a full scan on every visit. Paging with total counts on which the total count is returned for every row is a horrible bad idea (modeling wise, perf wise, sanity wise).
what am I doing wrong with my sql query? It always return an empty rows even if there is a value exist.
Here is my query:
SELECT *
FROM users
WHERE user_theme_id IN ( 9735, 9325, 4128 )
AND ( user_date_created BETWEEN '2013-06-04' AND '2013-06-10' );
I tried to cut my original query one by one, I got a result. Here is the first one:
SELECT * FROM users WHERE user_theme_id IN (9735, 9325, 4128 );
I got 3 rows for this result. See attached snapshot:
Now, the next query that I run is this:
SELECT *
FROM users
WHERE user_date_created BETWEEN '2013-06-04' AND '2013-06-10';
I do get 3 results on this. See attached snapshot:
By the way, this sql that uses BETWEEN should suppose return 4 rows but it only return 3. It doesn't return the data which has the created date of 2013-06-10 08:27:43
What am I doing wrong with my original query Why does it always return an empty rows?
If you are getting results by separately running different where clauses doesn't guarantee that AND 2 where clauses will return an answer.
There has to be intersection of rows to get result while AND.
You should validate your data and see if overlapping exists.
I have able to make it work by not using the SQL BETWEEN operators but instead COMPARISON OPERATORS like: >= || <=
I have read it from W3schools.com, the SQL between can produce different results in different databases.
This is the content:
Notice that the BETWEEN operator can produce different result in different databases!
In some databases, BETWEEN selects fields that are between and excluding the test values.
In other databases, BETWEEN selects fields that are between and including the test values.
And in other databases, BETWEEN selects fields between the test values, including the first test value and excluding the last test value.
Therefore: Check how your database treats the BETWEEN operator!
That is what happened in the issue that I am facing. The first field was being treated as part of the test values and the 2nd field was being excluded. Using the comparison operators give accurate result.
What is the difference between "TOP" and "SAMPLE" in TeraData SQL? Are they the same?
From TOP vs SAMPLE:
TOP 10 means "first 10 rows in sorted
order". If you don't have an ORDER BY,
then by extension it will be
interpreted as asking for "ANY 10
rows" in any order. The optimizer is
free to select the cheapest plan it
can find and stop processing as soon
as it has found enough rows to return.
If this query is the only thing
running on your system, TOP may appear
to always give you exactly the same
answer, but that behavior is NOT
guaranteed.
SAMPLE, as you have observed, does
extra processing to try to randomize
the result set yet maintain the same
approximate distribution. At a very
simple level, for example, it could
pick a random point at which to start
scanning the table and a number of
rows to skip between rows that are
returned.
‘Sample’ command:
Sel * from tablename
sample 100
That will give you a sample of 100 different records from the table.
The SAMPLE command will give DIFFERENT results each time you run it.
TOP command:
sel top 100 * from tablename;
This will give the first 100 rows of the table.
The TOP command will give you THE SAME results each time you run it.
When I need to get the number of row(data) inside a SQLite database, I run the following pseudo code.
cmd = "SELECT Count(*) FROM benchmark"
res = runcommand(cmd)
read res to get result.
But, I'm not sure if it's the best way to go. What would be the optimum way to get the number of data in a SQLite DB? I use python for accessing SQLite.
Your query is correct but I would add an alias to make it easier to refer to the result:
SELECT COUNT(*) AS cnt FROM benchmark
Regarding this line:
count size of res
You don't want to count the number of rows in the result set - there will always be only one row. Just read the result out from the column cnt of the first row.
I have a Product Class which has a one to many relationship to a Price class.
So a product can have multiple prices.
I need to query the db to get me 10 products which have Price.amount < $2. In this case its to populate a UI with 10 items in a page.
so i writ the following code:
ICriteria criteria = session.CreateCriteria(typeof(Product));
criteria.SetFirstResult(pageNumber);
criteria.SetMaxResults(numberOfItemInPage);
criteria = criteria.CreateCriteria("PriceCollection");
criteria.Add(Restrictions.Le("Amount", new Decimal(2)));
criteria.SetResultTransformer(CriteriaSpecification.DistinctRootEntity);
Instead of getting 10 Product on the list, I'm getting less than that (i.e. 5).
The reason being SetMaxResults(10) return me 10 Products but with duplicates. The duplicates are then removed by SetResultTransformer(DistinctRootEntity).
Can anyone tell me any way for me to get 10 unique Products without increasing SetMaxResults()? I need to use pagenumber as some sort of indexing.
That would be up to the SQL to decide, depending on what happens in the methods that gets the list you need to change the SQL so that it behaves as you like.
But being Distinct, you shouldnt get any duplicates.
It seems your duplicates problem stems from the fact that you are joining two tables and so you can get the same product as many times as you have prices for it.
How about adding 2 extra columns to your product table:
MinimumPrice (numeric(18,2)
MaximumPrice (numeric(18,2)
Whenever your system amends pricing for a product you update these two fields on the product. Now you can write a SQL query like the following:
SELECT TOP 10 * FROM Product
WHERE MinimumPrice > 2.0
And you will not have duplicate products.
Would the order of the statements make a difference? It looks like it's setting the maximum count early, and weeding out duplicates at the end, which applied in that order could end up with less than what you limited it to, consistent with what you described happening.
I would think you would need to effectively get all of the results, then apply the restriction (and possibly a sort?) and weed out the duplicates, and then finally apply your paging or count limit to those to get the first 10, next 10, and so on. So reordering the statements to reflect this logical order might help fix your bug.