I got headache of this query issue in CodeIgniter
I'm a beginner of this framework
How to query in CodeIgniter of Query result in Table 1 and Table 2.
If you are using the Query Builder in Codeigniter version 3 (I assume since your using the tag codeigniter-3), then you could specify the columns in your select statement and use join to achieve what you want:
$this->db->select('t1.Account, t1.Client, t1.Wala, t2.Meron');
$this->db->from('Table1 t1');
$this->db->join('Table2 t2', 't1.Account = t2.Account AND t1.Client = t2.Client');
$this->db->where('t1.Account', 111); // IF YOU ONLY WANT A SPECIFIC ACCOUNT
$this->db->group_by('t1.Account, t1.Client');
$query = $this->db->get();
if ($query->num_rows() > 0){
$result = $query->result(); // ARRAY OF OBJECTS
foreach ($result as $r){
echo $r->Account."\t";
echo $r->Client."\t";
echo $r->Wala."\t";
echo $r->Meron."\n";
}
}
The result:
| Account | Client | Wala | Meron |
|---------|--------|------|-------|
| 111 | Doe | | 50 |
| 111 | Jhon | 200 | 50 |
Documentation: https://www.codeigniter.com/userguide3/database/query_builder.html
Alternatively, you can use a pure SQL query to get the same result:
$sql = 'SELECT t1.Account, t1.Client, t1.Wala, t2.Meron
FROM Table1 t1
JOIN Table2 t2
ON t1.Account = t2.Account AND t1.Client = t2.Client
WHERE t1.Account = 111
GROUP BY t1.Account, t1.Client';
$query = $this->db->query($sql);
If you are using MySQL > 5.6 then use the group by function any_value():
t1.Account, t1.Client, ANY_VALUE(t1.Wala), ANY_VALUE(t2.Meron)
To be used with caution since unexpected results may appear if you have multiple rows with different values in the columns "Wala" or "Meron" for the same Account and Client.
Related
TABLE 1
student_id | name
-----------------
1 | A
2 | B
3 | C
4 | D
TABLE 2
vote_id | student_id | vote_for
------------------------------
1 | 1 | 2
2 | 1 | 3
3 | 2 | 1
4 | 1 | 4
How can I get records from TABLE 1 (student names B C D) based on student_id in TABLE 2 (student_id 1) in a single query? I managed to do it but in multiple queries like below:
$students = array();
$query = "SELECT vote_for FROM table2 WHERE student_id=?";
$stmt = $this->con->prepare($query);
$stmt->bind_param("i",$student_id);
$stmt->execute();
$stmt->bind_result($vote_for);
$votes = array();
while($stmt->fetch()){
$votes[] = $vote_for;
}
$stmt->close();
if (!empty($votes)) {
$query = "SELECT name FROM table1 WHERE student_id=?";
foreach ($votes as $vote) {
$stmt = $this->con->prepare($query);
$stmt->bind_param("i",$vote);
$stmt->execute();
$stmt->bind_result($name);
while($stmt->fetch()){
$temp = array();
$temp['name'] = $name;
$students[] = $temp;
}
$stmt->close();
}
}
You can use a JOIN query to get the names of the students that were voted for by a given student_id. For example:
SELECT s.name AS voted_for
FROM table2 v
JOIN table1 s ON s.student_id = v.vote_for
WHERE v.student_id = 1
Demo on dbfiddle
In PHP:
$students = array();
$query = "SELECT s.name AS voted_for
FROM table2 v
JOIN table1 s ON s.student_id = v.vote_for
WHERE v.student_id = ?";
$stmt = $this->con->prepare($query);
$stmt->bind_param("i",$student_id);
$stmt->execute();
$stmt->bind_result($name);
while($stmt->fetch()) {
$students[] = array('name' => $name);
}
$stmt->close();
I believe you can achieve it with the following query:
SELECT T1.STUDENT_ID, T1.NAME
FROM TABLE_1 T1, TABLE_2 T2
WHERE T1.STUDENT_ID = T2.VOTE_FOR
AND T2.STUDENT_ID = ?
And you would just inject the STUDENT_ID for the Table 2. You can remove the T1.STUDENT_ID if necessary.
This is my full code:
<?php $sid = $_SESSION['userid'];
$stmt = $pdo->prepare("
SELECT tableA.*, tableB.*, tableC.*
FROM tableA
LEFT JOIN tableB
ON tableA.tableAuserid = tableB.tableAuserid
LEFT JOIN tableC
ON tableA.tableAuserid = tableC.tableCuserid
WHERE tableA.tableAuserid = ?
;
");
$stmt->bindParam(1, $sid, PDO::PARAM_INT);
$stmt->execute();
$columns = $stmt->fetchAll();
foreach($columns as $column):
$tableAdate = $column['tableAdate'];
$tableBdate = $column['tableBdate'];
$tableCdate = $column['tableCdate'];
if ($tableAdate): ?>
<div><?php echo $tableAdate; ?></div>
<?php endif;
if ($tableBdate): ?>
<div><?php echo $tableBdate; ?></div>
<?php endif;
if ($tableCdate): ?>
<div><?php echo $tableCdate; ?></div>
<?php endif;
endforeach; ?>
My 3 database tables are: tableA:
tableAid | tableAuserid | tableAdate
1 | 44 | 2018-07-13 11:09:11
2 | 44 | 2019-05-23 01:21:29
tableB:
tableBid | tableBuserid | tableBdate
1 | 44 | 2019-08-11 17:41:01
And tableC:
tableCid | tableCuserid | tableCdate
1 | 44 | 2014-03-14 09:18:16
This is the result that's currently being echoed from my code:
2018-07-13 11:09:11
2019-08-11 17:41:01
2014-03-14 09:18:16
2019-05-23 01:21:29
2019-08-11 17:41:01
2014-03-14 09:18:16
But this is the result I want achieved from the code:
2019-08-11 17:41:01 (tableB)
2019-05-23 01:21:29 (tableA)
2018-07-13 11:09:11 (tableA)
2014-03-14 09:18:16 (tableC)
Basically each record must be retrieved with no duplicate values, result must be determined by the $_SESSION['userid'] variable, ORDER arrangement of SQL code must be by the latest date DESC of all dates combined from all 3 tables. How would I accomplish this?
Feel like I am missing some nuance of the question but perhaps not. Lot's of ways to accomplish this.
The following UNION allows for a fair amount of flexibility, that is, the ability to refine criteria per table and still sort on the SQL side of things.
SELECT tId, tUserId, tDate FROM tableA WHERE tUserId = ?
UNION ALL
SELECT tId, tUserId, tDate FROM tableB WHERE tUserId = ?
UNION ALL
SELECT tId, tUserId, tDate FROM tableC WHERE tUserId = ?
ORDER BY tDate DESC;
I honestly don't write many of these. Maybe in large part because of ORMs (something to look into), or as the conversation has leaned towards, design. Your first take with the left join is the format of probably 95% of the queries I write. Anyway though, there is no reason not to use a union for certain reporting needs. Maybe even create a view *gasp*.
first your SQL is not correct tableB dose not have the column tableB.tableAuserid
SELECT tableA.*, tableB.*, tableC.*
FROM tableA
LEFT JOIN tableB
ON tableA.tableAuserid = tableB.tableBuserid
LEFT JOIN tableC
ON tableA.tableAuserid = tableC.tableCuserid
WHERE tableA.tableAuserid = 44
ORDER BY tableAdate desc, tableBdate desc, tableCdate DESC
id | number
---|--------
1 | null
2 | 1
3 | null
4 | 0
5 | 4
6 | 4
This is what I want to do this in one query. How can I combine both of these queries together?
$id = 4;
SELECT * FROM users WHERE id = $id OR number = $id
// This will return rows 4,5,6
2nd query:
$id = 5;
SELECT * FROM users WHERE id = $id AND id = $numberColumnOfId AND number = $numberOfColumnId;
// This will return rows 4,5,6
$numberColumnOfId is the number of the $id. So if the $id = 5, then the number would be 4. So select rows where ID = 5.
How can I combine both of the SELECT statements together?
Use two queries that you combine with UNION.
The first query gets the rows with the given $id, the second query gets the ones that match via thenumber` column.
SELECT *
FROM users
WHERE id = $id OR number = $id
UNION
SELECT u1.*
FROM users AS u1
JOIN users AS u2 ON u1.number = u2.number OR u1.id = u2.number
WHERE u2.id = $id or u2.number = $id
DEMO
I am working on an old mysql data base (not created by me). It has 300k users, users are either flagged with flag=0, flag=1 or flag=1 and flag=0. The latter means that user was flagged in the past and currently is no longer flagged. The table looks like:
user_id | log_data | action | data |
001 | 1-1-2002 | flip-flag | flag=0 |
002 | 2-2-2003 | flip-flag | flag=1 |
002 | 2-3-2003 | flip-flag | flag=0 |
003 | 3-3-2003 | flip-flag | flag=1 |
I am trying to create a list containing only the users that were flagged in the past and are no longer flagged (flag=1 and flag=0, user_id=002 in the table above) I tried:
select user_id, data
from table_name
where (data = 'flag=1' and data = 'flag=0')
limit 50;
but it does not return any result. Doing:
select user_id, data
from table_name
where data = 'flag=1' limit 50;
gives the list of all users flagged with flag=1 (current flagged and past flagged). Does anybody know what to do in this case?
Hmmm . . . I'm thinking aggregation and having:
select user_id
from table_name
group by user_id
having max(case when data = 'flag=1' then log_date end) <
max(case when data = 'flag=0' then log_date end);
Just to be clear, the following query that you wrote will never return any data - the same row cannot have data = 'flag=1' and data='flag=0' which is why you'll have to use aggregation or a self join to get this right.
select user_id, data
from table_name
where (data = 'flag=1' and data = 'flag=0')
limit 50;
Another solution (probably less effective than Gordon's version)
select t0.user_id
from table_name t0
where (select t1.logdate from table_name t1 where t1.user_id = t0.user_id
and data = 'flag=1' order by 1 desc limit 1) >
(select t2.logdate from table_name t2 where t2.user_id = t0.user_id
and data = 'flag=0' order by 1 desc limit 1)
group by t0.table_name
I have a table with two columns:
ID1 | ID2
---------
1 | A
3 | V
1 | C
4 | B
5 | Q
1 | S
And I want to be able to find out if any row has, say ID1 = 5 and ID2 = Q , and return a true / false value.
Yes, Of course
SELECT * FROM table where ID1='5' and ID2='Q'
PHP (I am just guessing this backend)
$query = "SELECT * FROM table where ID1='5' and ID2='Q'";
$result = mysql_query($query);
if(mysql_num_rows($result)) { return true; }
else { return false; }
1 means TRUE for mysql
SELECT 1
FROM your_table
WHERE ID1 = 5 AND ID2 = 'Q'
for example this?
SELECT 1
FROM TABLE
WHERE ID1 = 5 AND ID2 = 'Q'
Efficient query for your purpose (faster than other examples):
SELECT 1 FROM table where ID1='5' and ID2='Q' LIMIT 1
PHP sample:
<?php
$query = "SELECT 1 FROM table where ID1='5' and ID2='Q' LIMIT 1";
echo bool(mysql_num_row(mysql_query($query)));
?>