I have a form that collects RSVPs for a party. The person filling out the form (Name) has an option to bring a guest (Guest). In the notification email, I am trying to give an accurate count of RSVPs with total Name and Guest counts.
It is easy to do if I was just getting the Name count (for person filling out the form):
mysql_query($query);
$result = mysql_query("select * from tablename");
$rowCount = mysql_num_rows($result);
mysql_close($link);
and I would simply use $rowCount as the total number of RSVPs. But I also want to include Guests in the count. The Guest is entered as GuestFirstName and GuestLastName in the form and goes on the same record as the person filling out the form. So I tried this. It worked when I included a guest - it said total RSVPs were 2. But when I did not include a guest on the next test I did, it also counted it as 2. Here is the code I used for that:
mysql_query($query);
$result = mysql_query("select * from tablename");
$result_guest = mysql_query("select * from tablename WHERE
GuestFirstName IS NOT NULL);
$rowCount = mysql_num_rows($result) + mysql_num_rows($result_guest) ;
mysql_close($link);
Like I said, this code yields 2 RSVPs even when no guest is entered. Any help would be appreciated. Thanks.
cdr6800
and
You can achieve this in a single query like the following. Also try to use PDO or mysqli_* functions because you use mysql_* which are deprecated.
SELECT
COUNT(*) AS total_names,
COUNT(CASE WHEN GuestFirstName IS NOT NULL THEN 1 END) AS total_guests
FROM tablename;
So, if there are 10 invitation rows and only 4 of them have guests results will be:
total_names total_guests
10 4
That's an expensive way to get a count of rows: selecting all columns from all rows in the table, and fetching those from the database to the client, to get just a "count" of the number of rows.
SQL provides aggregate functions. For example COUNT() can be used to return a count of rows.
As far as why you are getting two rows returned...
WHERE GuestFirstName IS NOT NULL
The most likely explanation is that there are two rows in the table which have a non-NULL value assigned to the GuestFirstName column. It may be an empty (zero-length string), which isn't considered NULL. Consider
SELECT '' IS NULL -- 0 (false)
, '' IS NOT NULL -- 1 (true)
I think you probably also want to exclude from the count rows where the GuestFirstName is equal to the empty string.
The PHP mysql_ extension is deprecated, and will be removed in future release. Two suitable replacements are available: PDO and mysqli.
And use a query that returns a single row with a count of rows. That will be more efficient than returning the entire table, just to get a count.
And do it in one pass through the data. For a row that includes a Guest, increment the count by 2, otherwise increment the count by 1. Use a SUM() aggregate, with an expression that returns either 2 or 1.
For example:
SELECT SUM(IF(t.GuestFirstName<>'',2,1)) AS total_including_guests
, SUM(1) AS count_rsvp
FROM mytable t
Maybe Guest Name has an empty (but not null) value. Try:
$result_guest = mysql_query( select * from tablename
WHERE GuestFirstName IS NOT NULL
AND GuestFirstName != '');
You can actually do this with one query and no additional logic, using SUM()
SELECT SUM(IF(GuestFirstName IS NULL, 1, 2)) AS totalGuests FROM tablename;
This will iterate over all rows and and sum up 1 (if 1 guest in this row is coming) or 2 (if "main" guest + his invite are coming)
Related
I am counting the entries in my SQL database:
$sql = "SELECT * FROM files WHERE id = ?";
$q = $pdo->prepare($sql);
$q->execute([$id]);
$rowCount =$q->rowCount();
The result of $rowCount is 500000.
But to output this single number takes 5 seconds! Is it possible to get this result faster?
Use the COUNT() function https://dev.mysql.com/doc/refman/8.0/en/counting-rows.html:
$sql = "SELECT COUNT(*) FROM files WHERE id = ?";
Also ensure that 'id' is an indexed column:
https://dev.mysql.com/doc/refman/8.0/en/mysql-indexes.html
Replace * with a field(use auto-increment id) - This will reduce the time a bit.
Index that field. - If you use indexed field the query performance will increase.
SELECT * ..., then counting in PHP, requires shoveling all columns of all rows back to PHP. That's a lot of effort for very little gain.
SELECT COUNT(col) ... does the counting in by MySQL, but it must check for whether col is NULL. And it needs to get at the value of col for every row.
SELECT COUNT(*) ... counts the rows by whatever way is most efficient. This involves looking for the 'smallest' index (or the whole table, if no secondary indexes), and counting through it.
You must learn about INDEXes to get anywhere in databases! This is only one minor use for them.
SQL Queries /P1/
SELECT EXISTS(SELECT /p2/ FROM table WHERE id = 1)
SELECT /p2/ FROM table WHERE id = 1 LIMIT 1
SQL SELECT /P2/
COUNT(id)
id
PHP PDO Function /P3/
fetchColumn()
rowCount()
From the following 3 Parts, What is the best method to check if a row exists or not with and without the ability to retrieve data like.
Retrievable:
/Query/ SELECT id FROM table WHERE id = 1 LIMIT 1
/Function/ rowCount()
Irretrievable
/Query/ SELECT EXISTS(SELECT COUNT(id) FROM table WHERE id = 1)
/Function/ fetchColumn()
In your opinion, What is the best way to do that?
By best I guess you mean consuming the least resources on both MySQL server and client.
That is this:
SELECT COUNT(*) count FROM table WHERE id=1
You get a one-row, one-column result set. If that column is zero, the row was not found. If the column is one, a row was found. If the column is greater that one, multiple rows were found.
This is a good solution for a few reasons.
COUNT(*) is decently efficient, especially if id is indexed.
It has a simple code path in your client software, because it always returns just one row. You don't have to sweat edge cases like no rows or multiple rows.
The SQL is as clear as it can be about what you're trying to do. That's helpful to the next person to work on your code.
Adding LIMIT 1 will do nothing if added to this query. It is already a one-row result set, inherently. You can add it, but then you'll make the next person looking at your code wonder what you were trying to do, and wonder whether you made some kind of mistake.
COUNT(*) counts all rows that match the WHERE statement. COUNT(id) is slightly slower because it counts all rows unless their id values are null. It has to make that check. For that reason, people usually use COUNT(*) unless there's some chance they want to ignore null values. If you put COUNT(id) in your code, the next person to work on it will have to spend some time figuring out whether you meant anything special by counting id rather than *.
You can use either; they give the same result.
Let's say I have a table with following columns: id-1, id-2, col-1, col-2, col-3
Here, id-1 is the primary key and is auto-incremented. id-2 is a different id and is not necessary to be unique. There are multiple instances of same id in that column. col-1, col-2, col-3 are just necessary columns.
I pass a query to select data from the table.
mysqli_query($connect, SELECT * FROM table WHERE id-2='some_specific_id')
It will return multiple rows. I would like to know how can I target specific rows, say row number 3.
First, use ":
mysqli_query($connect, "SELECT * FROM table WHERE id-2 = 'some_specific_id'");
Target specific row? Do you mean to limit the fetched rows? Or get the 3rd row?
For limiting the fetched rows, you can use LIMIT:
SELECT * FROM table WHERE id-2='some_specific_id' LIMIT 3
For getting the third row:
SELECT * FROM table WHERE id-2='some_specific_id' LIMIT 2, 1
Well although it seems you just rather needed to learn basic SQL to get your answer, there is still the question in the title, that may attract other people whose problem is formulated exactly like that. So goes the answer:
Mysqli is not very convenient for this task, so we would use PDO.
In case your query is intended to return multiple rows and you need to address one of them by number (which is rather makes little sense, but anyway), use fetchAll() method:
$stmt = $connect->prepare("SELECT * FROM table WHERE id2=?");
$stmt->execute(['some specific id']);
$data = $stmt->fetchAll();
and you will be able to address returned rows by number, starting from zero:
echo $data[0]['col1'];
However, it makes more sense to address the returned rows by some unique id. In this case just add this unique field fiset in the field list and then use the special PDO street magic:
$stmt = $connect->prepare("SELECT id1, table.* FROM table WHERE id2=?);
$stmt->execute(['some specific id']);
$data = $stmt->fetchAll(PDO::FETCH_UNIQUE);
and you will be able to address returned rows by that unique field :
echo $data[$id1]['col1'];
Use LIMIT to get what you want like:
SELECT * FROM table WHERE id-2='some_specific_id' LIMIT 2, 1;
Or, if you want to fetch from array, then use the 3rd index of array.
LIMIT Explanation:
The following illustrates the LIMIT clause syntax with two arguments:
SELECT
column1,column2,...
FROM
table
LIMIT offset , count;
Let's examine the LIMIT clause parameters:
The offset specifies the offset of the first row to return. The offset of the first row is 0, not 1.
The count specifies the maximum number of rows to return.
Hi I have this situation:
$query = $db->query('SELECT COUNT(*),* FROM memberFileReports');
$data = $query->fetch(PDO::FETCH_ASSOC);
print_r($data);
its not working ? any idea why and how to Count and get all items at the same time, and what if I want to Count (*) and then next Select will have Limit 0,5?
Is this what you're looking for?
SELECT * , CONCAT('', (SELECT COUNT(*) FROM memberFileReports)) AS total
FROM memberFileReports LIMIT 0,5
EDIT 1: Note that the 'total' will be a string
EDIT 2: As I understand , you want to get the total rows in the table, but only select 5 of them (as example)
EDIT 3: caps... and misspell
Use this
SELECT * , COUNT(*) FROM memberFileReports Group by column_id
Instead of this
SELECT COUNT(*),* FROM memberFileReports
EDIT:
try this
$data = $query->fetchAll();
instead of
$data = $query->fetch(PDO::FETCH_ASSOC);
I know this post is a little late but i figured i would tell you, the reason why you only get one row back is because you are using an aggregate function "COUNT()". that function makes it so the result is returned in one row. the way to show stuff in more than one row is to use a "GROUP BY" in your select statement and it will group the data by the condition you tell it to.
example... suppose we had an example table with 3 users..
one has 10 interactions
one 3
and one 33:
SELECT
e.UserID,
COUNT(e.interactions) as num_interactions
FROM example e
GROUP BY e.UserID;
that would show the number of interactions a user has made in the dummy example table.
OUTPUT:
UserID num_interactions
1 3
2 10
3 33
without the GROUP BY the aggregate would make the output look like this:
UserID num_interactions
1 46
just for future reference :)
Simply put, how can I count how many rows there are before a certain row. I'm using incremental ID's, but rows are deleted a random, so just checking to see what the ID is won't work.
If I have, say, 30 rows, and I've selected one based on a name (or anything really), how many rows are there before that one? It could be 16, 1, 12, or anything.
I'm using MySQL and CodeIgniter.
I assume your primary key column has datatype integer
SELECT COUNT(*) FROM `table`
WHERE id < (SELECT id FROM `table` WHERE `conditions are met for specific row`)
Assuming it's an auto_increment column, deleted rows won't be filled in again so this should do the job.
SELECT COUNT(*) FROM table WHERE id_column < your_selected_row_id;
On your model:
$id = $this->db->get('users')->where("name", "John")->id;
$rows = $this->db->get('users')->where("id < ", $id)->num_rows();
return $rows;
Notice how I'm using "chained methods" and for that you need PHP5 which is the default for CI 2.
You first need to get the ID of the record you need to start counting "backwards" which is the first line, considering a table called users and that the column you are filtering is "name" and the row you want to find has the name value of John.
The second line will give you the number of rows that the query "where id < number" returned where number is the ID you got from the first query. Maybe you can even chain both lines.