SQL Query Count across 2 tables - php

Here is what I have (i am including only the relevant cells to each table)
table1:
- user_id
table2:
- id
- manager_id
... and I have a PHP variable
$manager_id
So, what I am trying to do is get a COUNT(*) of how many records exist in table1, but the record should only be counted if table1.user_id (which is the table2.id) has a table2.manager_id == $manager_id
So, the only way I know how to do this would be to do something like this in PHP (which is wildly inefficient):
$query = "SELECT user_id FROM table1 WHERE {my where clause}";
// execute query and place into $item[] array (not shown for brevity)
foreach ( $item as $user_id ) {
$query = "SELECT manager_id FROM table2 WHERE id = '{$user_id}';
// execute query, place each item into $row
if ( $row['manager_id'] == $manager_id ) {
// tick up count by 1
}
I am fairly certain there is a way to do this purely in SQL, but I am at a loss.

You could try the below query:
select count(1) from table1 t1, table2 t2 where t1.user_id = t2.id and t2.manager_id = ?

you need to set your where clause to have this condition i.e.
SELECT Count(user_id) FROM table1 where
table1.user_id = table2.id
AND Convert('Varchar', table2.manager_id) = $manager_id
I assume your php variable $manager_id has a string
if it is not a number then there is no need to convert the sql column (table2.manager_id) to varchar.

You can do this with one SELECT statement:
SELECT COUNT(*)
FROM table1
WHERE user_id IN (
SELECT id
FROM table2
WHERE manager_id = <your-value-of-manager-id>
)
In case you need to use the data and want to count on PHP side you can use the following SELECT statement using a LEFT JOIN:
SELECT table1.*
FROM table1 LEFT JOIN table2 ON table1.user_id = table2.id
WHERE table2.manager_id = <your-value-of-manager-id>
To execute the SELECT statements you should use prepared statements (using PDO or mysqli).
example using the first query:
$sql = 'SELECT COUNT(*) FROM table1 WHERE user_id IN (SELECT id FROM table2 WHERE manager_id = ?)';
$sth = $dbh->prepare($sql);
$sth->execute([$manager_id]);
$rows = $sth->fetchAll();
if (count($rows) === 1) {
echo $rows[0][0];
}
example using the second query:
$sql = 'SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.user_id = table2.id WHERE table2.manager_id = ?';
$sth = $dbh->prepare($sql);
$sth->execute([$manager_id]);
$rows = $sth->fetchAll();
echo count($rows);

Related

PHP MySQL Count rows from INNER JOIN - GROUP BY

What I'm trying to do here, is I want to output the count of the id and user_id columns from items, by users which have the rank 1.
Let's say there's 8 rows in items which have a base_item of 400, and these 8 rows, where 2 rows of them has a user_id of 4 and the existing left has a user_id of 6 The output should then be:
$countItems = 8 and $countUsers = 2.
$stmt = $conn->pdo->prepare("
SELECT COUNT(*),`user_id` FROM `items`
INNER JOIN `users`
ON `users`.`id` = `items`.`user_id`
WHERE `base_item` = :i AND `rank` = 1
GROUP BY `user_id`,`items`.`id`
");
$data = array(':i' => '400'); // item_id in `values` table
$stmt->execute($data);
if($inv = $stmt->fetch($db->FETCH_ASSOC)) {
$countItems = $inv['id'];
$countUsers = $inv['user_id'];
}
I have tried several methods, but I still keep getting output 2 and 2 even though the results should be 8 and 2.
Table Info for values:
Table Info for items:
First of all you never want to fetchAll() and discard the data just to count the number of rows. There is a better way.
SELECT COUNT(*) FROM `items` WHERE `base_item` = :item AND `user_id` = :uid
Secondly, you should try to avoid a nested loop whenever possible because nested loops don't scale very well. And the solution is to use a join or a subquery. You haven't posted your table structures, so this query is untested.
SELECT COUNT(*), user_id FROM `items` INNER JOIN users
ON users.id = items.user_id
WHERE `base_item` = :item and rank =1 GROUP BY user_id
One query instead of two, a lot less number of lines of code.
Problem is that you're replacing $smst withing the foreach loop.
Use other variable name, for example:
$stmt->execute();
foreach($stmt as $user) {
$stmt2 = $conn->pdo->prepare("SELECT `id`,`user_id` FROM `items` WHERE `base_item` = :item AND `user_id` = :uid");
$stmt2->bindParam(':item', $cmsval['item_id'], $db->PARAM_INT);
$stmt2->bindParam(':uid', $user['id'], $db->PARAM_INT);
Well, all I actually had to do, was remove GROUP BY and add COUNT DISTINCT instead, like following:
$stmt = $conn->pdo->prepare("
SELECT COUNT(DISTINCT `user_id`) as `uid`,
COUNT(`items`.`id`) as `id`
FROM `items`
INNER JOIN `users`
ON `users`.`id` = `items`.`user_id`
WHERE `base_item` = :i AND `rank` = 1
");
$stmt->bindParam(':i', $cmsval['item_id'], $db->PARAM_INT);
$stmt->execute();
if($inv = $stmt->fetch($db->FETCH_ASSOC)) {
$countItems = $inv['id'];
$countUsers = $inv['uid'];
}

How to search into table B if the result of searching into table A is zero?

I have three tables and I need to search in the first one, it there isn't any result, then search into second one and so on ..!
Here is my code:
// connecting to database
$stm1 = $this->dbh->prepare(" select * from table1 where col = :name; ");
$stm1->bindValue(":name", $name, PDO::PARAM_STR);
$stm1->execute();
$which_table = "table1";
// the result of searching into table1 is zero, then search into table2
if (!$stm1->rowCount()) {
$stm2 = $this->dbh->prepare(" select * from table2 where col = :name; ");
$stm2->bindValue(":name", $name, PDO::PARAM_STR);
$stm2->execute();
$which_table = "table2";
// the result of searching into table2 is zero, then search into table3
if (!$stm2->rowCount()) {
$stm3 = $this->dbh->prepare(" select * from table3 where col = :name; ");
$stm3->bindValue(":name", $name, PDO::PARAM_STR);
$stm3->execute();
$which_table = "table3";
// the result of searching into table3 is also zero
if (!$stm3->rowCount()) {
$which_table = 'none of them';
}
}
}
My code works as well, But it is slow, How can I optimize it and make it faster? As you see, there is three separated query and multiple if-statement .. How can I reduce them? Generally How can I improve that code? Can I do that using pure-sql?
If you code is slow, then you probably just need indexes:
create index idx_table1_col on table1(col);
create index idx_table2_col on table2(col);
create index idx_table3_col on table3(col);
With indexes, you can also phrase the query as a single statement, assuming the columns in the tables are the same:
select t1.*
from table1 t1
where t1.col = :name
union all
select t2.*
from table2 t2
where t2.col = :name and
not exists (select 1 from table1 t1 where t1.col = :name)
union all
select t3.*
from table3 t3
where t3.col = :name and
not exists (select 1 from table1 t1 where t1.col = :name) and
not exists (select 1 from table2 t2 where t2.col = :name);
This is a more complex query, but your code would only require a single query. And, with indexes, it should be very fast.
My code works as well, But it is slow, How can I optimize it and make it faster?
Add index for the column col
By the way, you may add limit 1 to your queries. It'll help you you have zillions of values in your tables to match

How we get unmatched values from tables in mysql databases

I have a problem in fetching data from mysql database tables.
I have two tables like table-1 and table-2 in below figure. How to get data from table-2 when pilotid is not equal to 1 in table-1.
I'm not sure, if I understand correctly, but this returns all rows of table-1, that do not have a matching entry in table-2. You can find the respective documentation of NOT EXISTS here.
SELECT *
FROM table-1 t1
WHERE NOT EXISTS( SELECT * FROM table-2 t2 WHERE t1.`Venueid` = t2.`Venueid` )
select a.venueid, a.name
from table2 a, table-1 b
where b.pilotid <> 1 and b.venueid = a.venueid;
SELECT Table_2.*
FROM Table_2
LEFT JOIN Table_1
ON Table_2.Venueid = Table_1.Venueid
WHERE Table_1.Venueid != 1
OR Table_1.Venueid NOT IN(1, 13, 15);
$sql = "select Venueid from Table1 where pilotid <> 1";
$data = mysql_query($sql);
while($row = mysql_fetch_assoc($data))
{
$ids[] = $row['Venueid'];
}
$sql2 = "select * from Table2 where venueid IN(".implode(',', $ids).")";
$data2 = mysql_query(sql2);
//$data2 contains the result-set resource;

php sql count from 3 tables

I need to get a count from a table, based on data from 2 other tables.
This is my tables structure:
table1 (id, name)
table2 (id, a, b, c)
table3 (id, blah)
Can i do it all in one statement? Something like this:
SELECT count(*) from table3 WHERE table2.x=table1.name
The hard part is the x column is the name of 'table1.name'. So i dont actually know what x is when im running the statement.
This makes me think i'd have to run a statement to find the name of x before i run this one.
Or... maybe some JOIN?
CURRENT CODE WHICH I USE:
if ($rs[firearm] != "") {
$sql_result2 = mysql_query("SELECT * FROM db_firearms WHERE name='$rs[firearm]'", $db);
$rs2 = mysql_fetch_array($sql_result2);
$sql_result3 = mysql_query("SELECT * FROM items_firearms WHERE player='$id'", $db);
$rs3 = mysql_fetch_array($sql_result3);
if ($rs3[$rs2[shortname]] < 1) {
mysql_query("UPDATE players SET firearm = '' WHERE id ='$id'");
}
}
Yeah, sounds like joins will be necessary.
SELECT count(*) AS num_rows
FROM table3
LEFT JOIN table1.name ON table1.name = table3.name
INNER JOIN table2 ON table2.x = table1.name

Fetch data from multiple MySQL tables

My two tables look like this:
TABLE1 TABLE2
+--------------------+ +--------------------+
|field1|field2|field3| and |field2|field4|field5|
+--------------------+ +--------------------+
I am already running a SELECT query for TABLE1, and assorting all of the data into variables:
$query = "SELECT * FROM TABLE1 WHERE field2 = 2";
$result = mysql_query($query);
$num_rows = mysql_num_rows($result);
if((!is_bool($result) || $result) && $num_rows) {
while($row = mysql_fetch_array($result))
{
$field1 = $row['field1'];
$field2 = $row['field2'];
$field3 = $row['field3'];
}
}
What I want to do is get the data from 'field4' on TABLE2 and add it to my variables. I would want to get field4 WHERE field2 = 2
SELECT
t1.*,
t2.field4
FROM
TABLE1 AS t1,
TABLE2 AS t2
WHERE
t1.field2 = 2
AND
t1.field2 = t2.field2
You want to join the two table which can be done explicitly (using the JOIN operator or one of its variants) our implicitly (by SELECTing from multiple tables directly).
From your description, I suppose that you want to do the join where field2 in the two tables have the same value (2).
If TABLE2 will not always provide a valid join candidate but you still want the data from TABLE1, you should use a LEFT JOIN (giving NULL for field4 where nothing matched):
SELECT
t1.*,
t2.field4
FROM
TABLE1 AS t1
LEFT JOIN
TABLE2 AS t2
ON
t1.field2 = t2.field2
WHERE
t1.field2 = 2
http://en.wikipedia.org/wiki/Join_%28SQL%29
You need to use a JOIN:
SELECT TABLE1.*,TABLE2.field4 FROM TABLE1 JOIN TABLE2 ON TABLE1.field2=TABLE2.field2 WHERE TABLE1.field2=2;
hi try the following as ur query.
It is not preferred all the time to use * in the select query
SELECT T1.field1,T1.field2,T1.field3, T2.field4 FROM TABLE1 AS T1 INNER JOIN TABLE2 AS T2 ON T1.field2=T2.field2 WHERE field2 = 2

Categories