Codeigniter merge into one row record with sql one to many relationship - sql

I would like to query one to many relationship
eg:
Table A: Table B:
id | country_name id | name | table_A_id
1 | Usa 1 | kerry | 1
2 | Australia 2 | jerry | 1
3 | tommy | 2
4 | cherry | 2
my purpose is to query the result to merge one row record
eg: result list:
1 Record 2 Record
Usa Australia
kerry tommy
jeryy cherry
Currently, I am using Codeignter framework and beginner for sql, please don't mind me guys.
$this->db->select('*')
>from("table A")
->join("table B", "table.A.id = table_A_id");
$query = $this->db->get();
if($query->num_rows() > 0) {
return $query->result();
}
My view
<?php foreach($posts as $post) {
echo $post->country_name;
echo $post->name;
} ?>
However, it gives me 4 row records.
1 Record 2 Record
Usa Usa
kerry jerry
3 Record 4 Record
Australia Australia
tommy cherry
Thanks you guys in advance for helping me.

Here is what you missed
$this->db->select('*')
>from("table A")
->join("table B", "table.A.id = table_A_id");
$query = $this->db->get();
if($query->num_rows() > 0) {
return $query->result();
}
it should have been
->join("table B", 'B.table_A_id=A.id');
hope this make sense
option B
$this->db->join('table B','B.table_A_id=A.id','INNER');
$query = $this->db->get('table A');

Try out this
SELECT country, group_concat(name) FROM city c INNER JOIN employee e
ON c.id = e.city_id group by c.id
output
('USA ' , 'jerry ,kerry'),
('Australia', 'cherry ,tommy');

My solution found without using inner join:
public function mergeRecord() {
$array_store = array();
foreach($this->one() as $row) {
$child = $this->many($row['id']);
if($child) {
$return = array_merge(array("parent" => $row), array("child" =>$child));
array_push($array_store, $return);
}
}
return $array_store;
}
public function one() {
$query = $this->db->select("*")
->get("table A")
->result_array();
return $query;
}
public function many($id) {
$query = $this->db->select("id, name")
->where("table_A_id", $id)
->get("table B")
->result_array();
return $query;
}

Related

How to get what percentage of total users joined what number of meetings in PostgreSQL?

There are two tables, one is called "user_preference" that contains all users:
id | firstname | lastname | email |
And "match" which combines users with meetups they joined:
id | matcher | partner | meetup |
Both matcher and partner are foreign keys that represent user_preference.id, meaning that same user can be both matcher and a partner in the same meetup.
What I need to know is what percentage of total unique users joined what number of meetings.
For example:
17% of users joined 5 meetups
20% of users joined 3 meetups
40% of users joined 1 meetup
23% of users joined 0 meetups
The number of meetups should not be hardcoded but dynamic.
But I want to avoid duplication of users for a single meetup and count them only once. For example this:
id | matcher | partner | meetup |
1 | user1 | user2 | meetup1 |
2 | user1 | user3 | meetup1 |
3 | user5 | user1 | meetup1 |
4 | user6 | user1 | meetup2 |
Should count that user1 visited only 2 meetups.
What I managed to do so far is to display the count of meetups each user visited but that is not what I need:
SELECT distinct up.email users, COUNT(m.user) meetups
FROM user_preference up
LEFT JOIN
(
SELECT matcher AS user FROM match
UNION ALL
SELECT partner AS user FROM match
) m ON m.user = up.id
GROUP BY up.email
ORDER BY meetups desc;
In the end I did this by making simple queries and looping through them in the code, its far from elegant solution but it should work.
If someone posts SQL solution I will accept and upvote it...
export const getDevStats = async () => {
const users = await getRepository(UserPreference).query(
`SELECT * FROM user_preference;`
);
const meetups = await getRepository(Meetup).query(
`SELECT * FROM meetup;`
);
const matches = await getRepository(Match).query(
`SELECT * FROM match;`
);
let userMatches: any = {};
users.forEach((user: any) => {
userMatches[user.id] = []
matches.forEach((match: any) => {
if(user.id == match.matcher || user.id == match.partner) {
if(userMatches[user.id].indexOf(match.meetup) === -1) {
userMatches[user.id].push(match.meetup);
}
}
});
});
let matchStats: any = {};
for (var userId of Object.keys(userMatches)) {
if (typeof matchStats[userMatches[userId].length] === 'undefined') {
matchStats[userMatches[userId].length] = 0;
}
matchStats[userMatches[userId].length]++;
}
return {
users: users,
meetups: meetups,
matches: matches,
userMatches: userMatches,
matchStats: matchStats
};
};

Filtering records city and state

I have 2 tables with name = city and state
city
id_city | name_city
1 | JED
2 | RUD
3 | DMM
state
id_state | id_for_city | name_state
1 | 1 | JED1
2 | 1 | JED2
3 | 2 | RUH1
4 | 2 | RUH2
I used ComboBox and i have 2
first combobox1 select name_city (it's ok )
second combobox2 i want select name_state through id_for_city but it left join id_city (here it,s not okay )
how i can write query by using left join in java ?
my code :
frst comboBox1 i think it,s ok
public void Filecombo() {
try {
String sql = "select name_city from city";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while (rs.next()) {
options.add(rs.getString("name_city"));
}
comboCity.setItems(options);
pstmt.close();
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
second comboBox2 (here probloem)
public void Filecombo2() {
try {
String sq2 = " select name_state from state left join city on city.id_city= state.id_from_city";
pstmt2 = conn.prepareStatement(sq2);
rs = pstmt2.executeQuery();
while (rs.next()) {
options2.add(rs.getString("name_state"));
}
comboBranch.setItems(options2);
pstmt.close();
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
the result If i want to select different cities like RUH or DMM or JED
combobox2 will appear Anything related combobox1
Your question does not seem to have much to do with Java, and I'll assume that your JDBC code is basically working, and you are already getting a result set, albeit perhaps not exactly what you want. I think you just need to add a WHERE clause to your query:
SELECT c.name_state
FROM state s
INNER JOIN city c
ON c.id_city = s.id_for_city
WHERE
s.name_city = 'JED';
Note that I replaced the left join with an inner join, since you want state names only, which come from the city table. A left join would be desirable if you wanted to return a NULL for the case of states which did not match to anything in the other table. But, that doesn't appear to be the case here.

Symfony/Doctrine: SUM and AVG score of players

I have in my database the tab: PLAYERS and a tab: SCORES.
In tab SCORES i have these rows: ID - IDPLAYER - SCORE
For example:
ID IDPLAYER SCORE
---------------------
1 1 5
2 2 4
3 1 3
4 2 1
5 1 9
I want put in a template this:
For "player 1" there are 3 scores.
The count of the scores is "17" (9+3+5).
The avg of the score of the player is "5.6" (17totscores / 3countScores).
I have an entity with ORM, it' ok.
I have a controller with this function:
public function avgScoreAction($id) {
$queryScore = $this->getDoctrine()
->getRepository('AcmeBundle:tabScores');
$queryAvgScore = $queryScore->createQueryBuilder('g')
->select("avg(g.score)")
->where('g.idPlayer = :idPlayer')
->setParameter('idPlayer', $id)
->getQuery();
$avgScore = $queryAvgScore->getResult();
$result = ("Score average: ".$avgScore);
return new Response($result);
But I have an error:
"Notice: Array to string conversion in this line:"
$result = ("Score average: ".$avgScore);
If I write this:
$response = new Response();
$response->setContent(json_encode(array($avgScore)));
$response->headers->set('Content-Type', 'application/json');
return $response;
I get this:
[[{"1":"5.6667"}]]
which is the correct avg, but what is: [[{"1":" and "}]] ?????
what is: [[{"1":" and "}]] ?
1 is the index of avg(g.score) in your query. To better understand why, try an echo of $queryAvgScore->getDql() before getResult().
Let's get back to the general question :
the SQL is :
SELECT AVG(SCORE) as AVG, COUNT(SCORE) as COUNT, IDPLAYER as PLAYER FROM SCORES GROUP BY IDPLAYER
and now with query builder :
$queryAvgScore = $queryScore->createQueryBuilder('g')
->select("avg(g.score) as score_avg, count(g.score) as score_count")
->where('g.idPlayer = :idPlayer')
->groupBy('g.idPlayer')
->setParameter('idPlayer', $id)
->getQuery();
Notice that i have added aliases, this is better than using indexes.
Hope it helps.
Symfony 2.6 is easy with DQL
$dql = "SELECT SUM(e.amount) AS balance FROM Bank\Entities\Entry e " .
"WHERE e.account = ?1";
$balance = $em->createQuery($dql)
->setParameter(1, $myAccountId)
->getSingleScalarResult();
Info:
http://doctrine-orm.readthedocs.org/en/latest/cookbook/aggregate-fields.html?highlight=sum

Simple relation in YII, can't get it done

This is the first time I use relations in Yii, the question is very simple.
MODULE TABLE
name - PK
status - FK status_id
STATUS TABLE
id PK
name
So, each Module HAS one status.
But I can not seem to get it working.
Module.php (Model)
public function relations()
{
return array(
'status'=>array(self::BELONGS_TO, 'ModuleStatus', 'status'),
);
}
I access them this way:
$modulesAR = Module::model()->with('status')->findAll();
if( $modulesAR )
{
foreach( $modulesAR as $moduleAR )
{
$this->modules[ $moduleAR->name ] = array(
'sessionLimit' => isset($moduleAR->sessionLimit) ? $moduleAR->sessionLimit : 0,
'status' => isset($moduleAR->status) ? $moduleAR->status : 'disabled',
);
}
}
Var_dump(Yii::app()->module->modules;
array(3) {
["digidoc"]=>
array(2) {
["sessionLimit"]=>
int(0)
["status"]=>
string(1) "2" // Should say "Disabled"
}
["docusearch"]=>
array(2) {
["sessionLimit"]=>
int(0)
["status"]=>
string(1) "1" // Should say "Enabled"
}
["printbox"]=>
array(2) {
["sessionLimit"]=>
int(0)
["status"]=>
string(1) "2" // Should say "Disabled"
}
}
I will appreciate any help.
Thanks!
EDIT:
query executed by Yii:
SELECT `t`.`name` AS `t0_c0`, `t`.`status_id` AS `t0_c1`, `t`.`session_limit` AS `t0_c2`, `status`.`id` AS `t1_c0`, `status`.`name` AS `t1_c1` FROM `ss_module` `t` LEFT OUTER JOIN `ss_module_status` `status` ON (`status`.`id`=`t`.`name`)
+------------+-------+-------+-------+-------+
| t0_c0 | t0_c1 | t0_c2 | t1_c0 | t1_c1 |
+------------+-------+-------+-------+-------+
| digidoc | 2 | 0 | NULL | NULL |
| docusearch | 1 | 2 | NULL | NULL |
| printbox | 2 | 0 | NULL | NULL |
+------------+-------+-------+-------+-------+
EDIT 2:
Changing the last
ON (`status`.`id`=`t`.`name`);
to
ON (`status`.`id`=`t`.`status_id`);
works as expected, by I dont know how to fix it in Yii.
When you peek into $moduleAR->status, you get the whole Status model instance, not it's id. So just go on and peek into that instance:
$moduleAR->status->name.
That's what ActiveRecord magic is intended for ;)
And inversely, if you have Status model, you should have a relation there saying something like this:
'modules' => array(self::HAS_MANY, 'Module', 'status_id')
Which could make the following possible:
$status = Status::model()->find(/*somehow*/);
/* now that $status is an Status instance */
foreach ($status->modules as $module) {
// here you are! looping over all modules connected to this status
// each $module is a full-fledged Module instance
}

Select query question

I have a table in a mysql-database with the fields
"name", "title", "cd_id", "tracks"
The entries look like this:
Schubert | Symphonie Nr 7 | 27 | 2
Brahms | Symphonie Nr 1 | 11 | 4
Brahms | Symphonie Nr 2 | 27 | 4
Shostakovich | Jazz Suite Nr 1 | 19 | 3
To get the tracks per cd (cd_id) I have written this script:
#!/usr/bin/env perl
use warnings; use strict;
use DBI;
my $dbh = DBI->connect(
"DBI:mysql:database=my_db;",
'user', 'passwd', { RaiseError => 1 } );
my $select_query = "SELECT cd_id, tracks FROM my_table";
my $sth = $dbh->prepare( $select_query );
$sth->execute;
my %hash;
while ( my $row = $sth->fetchrow_hashref ) {
$hash{"$row->{cd_id}"} += $row->{tracks};
}
print "$_ : $hash{$_}\n" for sort { $a <=> $b } keys %hash;
Is it possible to get these results directly with an appropriate select query?
"SELECT cd_id, SUM(tracks) as tracks FROM my_table GROUP BY cd_id"
edit: see here for further information and other things you can do with GROUP BY: http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html
Use an aggregate function
SELECT `cd_id`, SUM(`tracks`) AS s
FROM `your_table`
GROUP BY `cd_id`