Avoiding duplicates Database records in a datamapper code igniter - php

My Question is simply how to insert data into the join table(user_book) without inserting a duplicate entry into the main table(book).
Mainly consider we have tree table below
id Users id Books id Users Books
1 Sam 1 B1 1 1 1
2 Ben 2 B2 2 1 3
3 Mike 3 B3 3 3 3
4 2 2
But the problem is when I am inserting a new book(ex Mike like B3) that exist in the Books table. The duplicate will appear in the books table and the above table will be like:
id Users id Books id Users Books
1 Sam 1 B1 1 1 1
2 Ben 2 B2 2 1 3
3 Mike 3 B3 3 3 4
4 B3 4 2 2
Is that make sense now what I am trying to resolve? Or maybe I can't have a unique list of books at all?
if I am going to insert
Given the database
users and books
users<--->books are related by users_books
we need to make sure that when we insert a book record to the db it is not a duplicate. Further, if the book exist, a relation will be inserted and not the book record . How can one do that?
One approach is to say
$m=new Book();
$m->where('id_book', $data['user_booklist'][$i]['id'])->get();
$u = new User();
$u -> where('id_user', $data['user_profile']['id'])-> get();
if(!$u->where_related($m))
{
$m -> name = $data['user_booklist'][$i]['name'];
$m -> id_book = $data['user_booklist'][$i]['id'];
$m -> save($u);
}
if (book->exist) in the "books" table
then check the relation and see if there is a relationship between users and books and if there is then don't insert it. Further do I need to change any thing in the mysql db structure to avoid this.
The above code is not working but should give an idea what I am talking about.
Update:
In summary, if two users liked the same book, I just want to insert a record(book) into the join table (users_books) and while not to creating a new record in the table. Using the unique sql tag did not work since it keeps unique list but it prevents from inserting the multiple relationships into the join table users_books.

You could do:
$b = new book();
$b->where('id_book', $data['user_booklist'][$i]['id'])->get();
// I believe you can do this as well, but I'm not sure:
// $b->where('id', $data['user_booklist'][$i]['id'])->get();
$u = new user();
$u -> where('id_user', $data['user_profile']['id'])-> get();
if( $b->exists() && $u->exists() )
{
// This saves the relationship between the book and the user
$b->save($u);
}
else
{
// Could not find the book or the user
}
You should check out the datamapper-manual on saving relationships.

Related

How to get the Hierarchy recursively in laravel

I have 2 tables i.e. users and user_managers, with the following structure and data:
users
id
name
employee_number
1
Employee One
ACB1234
2
Employee Two
XYZ1234
3
Employee Three
EFG1234
4
Employee Four
HIJ1234
user_managers
id
user_id
manager_of_user_id
1
1
2
2
2
3
3
4
1
4
5
4
I want a recursive function to get the complete chain of the managers. For example, if query for user_id = 4, I should get the following result:
result
user_id
name
employee_id
comments
1
Employee One
ABC1234
user managed by 4
2
Employee Two
XYZ1234
user managed by 1
3
Employee Three
EFG1234
managd by user 2
5
Employee Five
JKL1234
manager of user 4
The table above is just for the clarification, I am looking for a recursive function to get the above result.
I have tried the below solution but it is working for only 1 level.
public static function getCompleteChain(User $user)
{
$managerUsers = $user->managers;
foreach ($managerUsers as $manager) {
$manager->user = User::where('employee_id', $manager->manager_of_user_id)->first();
self::getCompleteChain($manager->user);
}
return $managerUsers;
}
Thanks in advance.

Optimal way to store follower and following MySQL

I have 2 tables one is user and another is company. Both have the following columns common while other columns are different.
id email name
1 first#email.com First user
2 second#email.com Second User
3 third#email.com Third User
Now a user can follow many companies but a company does not follow back user. Company should have data with users who follow them and a user should also store the companies they are following.
What is the simplest and optimal to make this happen on MySQL? Either should I create separate table for it or just add a column on existing tables with array of followers. Please answer assuming I have working level of knowledge on PHP and MySQL.
You have the tables User and Company. Let's suppose they contain these values:
User
UserId
UserName
UserMail
1
Alice
alice#mail.com
2
Bob
bob#mail.com
Company
CompanyId
CompanyName
CompanyAddress
1
Microsoft
Redmond
2
Apple
Cupertino
3
Google
Mountain View
Then you should create a many-to-many table - e.g. let's call it UserCompany - which contains at least the columns UserId and CompanyId (coming from the first two tables).
Let's suppose that Alice follows Microsoft and Apple, and Bob follows Google. Your new UserCompany table will contain the following data:
UserId
CompanyId
1
1
1
2
2
3
Company should have data of users who follow them
Here you are the query to get the data of the users that follow Microsoft:
SELECT u.UserName, u.UserMail
FROM User AS u
JOIN UserCompany AS uc ON u.UserId = uc.UserId
WHERE uc.CompanyId = 1
User should also have data of companies they are following.
And here you are the query to get the data of the companies followed by Alice:
SELECT c.CompanyName, c.CompanyCity
FROM UserCompany AS uc
JOIN Company AS c ON c.CompanyId = uc.CompanyId
WHERE uc.UserId = 1
The simplest solution is to have a MANY-TO-MANY join table to link these 2 tables. You can do this with either 2 MANY-TO-MANY tables or a single one.
For example 2 table:
user_follows_company
ID CompanyID UserID
---- ------ ---------
1 1 5
1 1 6
1 1 8
1 2 5
You can get the companies a user follows by using the following SQL:
SELECT * FROM company c JOIN user_follows_company ufc on ufc.companyID = c.ID WHERE user = $USER_ID
company_follows_user
ID CompanyID UserID
---- --------- ---------
1 3 5
1 3 6
1 5 3
1 5 4
You can get the users a company follows by using the following SQL:
SELECT * FROM user u JOIN company_follow_user cfu on cfu.userID = u.ID WHERE user = $USER_ID
or you can do this with a single table and have a column that designates which direction is being followed:
follows_table
ID CompanyID UserID Initiator
---- --------- --------- ---------
1 3 5 Company
1 3 6 Company
1 5 3 Company
1 5 4 Company
1 5 1 User
1 6 1 User
1 8 1 User
1 5 2 User
Note that storing the "initiator" as a string is not a good idea - it probably should be an int or an ENUM
To query on this table, do the following queries:
Companies a user follows:
SELECT * FROM company c JOIN follows_table ft on ft.userID = c.ID WHERE user = $USER_ID AND ft.initiator = 'user'
Users a company follows:
SELECT * FROM user u JOIN follows_table ft on ft.userID = u.ID WHERE companyID = $$COMPANY_ID AND ft.initiator = 'company'

Query to join two table and sort the data array using PHP and MySQL

I need one help.I have two table i need to join two table and display them inside user's table.I am explaining my table structure below.
db_summary:
id member_id hit_type device_type
1 20 1 IOS
2 12 2 IOS
3 20 3 Android
4 14 4 Android
5 12 3 IOS
6 14 5 IOS
From the above table the hit_type column value is linked to the following table's type column.
db_hit_type:
id name type
1 Page 1
2 Map 2
3 Gallery 3
4 Phone 4
5 Web 5
From the db_summary table if hit_type=1 means its a page hit which is defined in second table. Here i need to fetch both table data by joining and sort them as per member id to display in following user's ui table.
sl no member page Hit Map Hit Gallery Hit Phone Hit WebHit TOTAL
i need to fill the above table by using the db data.suppose for member id 20 how many nos of page hit,Map hit...... and total nos of hit.I need to fetch all data and sort them as per user's table structure.Please help me.
Use below query to get both table data
SELECT * FROM db_summary AS ds, db_hit_type AS dht WHERE ds.hit_type = dht.type GROUP BY ds.member_id
SELECT dbs.*,dbht.name,dbht.id as dbHitId
FROM db_summary as dbs
LEFT JOIN db_hit_type as dbht
ON dbs.hit_type=dbht.type
ORDER BY dbs.member_id
I don't know how or when you want to view the resulting data, but at some point you will need to run a query counting each type of hit per user from the db_summary table, then updating the user table with the resulting data.
You could do something like this:
$stmt = $db->prepare("SELECT * FROM `db_summary` WHERE `member_id` = :member");
$stmt->bindParam(':member', $memberid);
$stmt->execute();
$hit = array(0,0,0,0,0);
while ($row = $stmt->fetch(PDO::ASSOC))
{
++$hit[$row['hit_type']-1];
}
echo 'Type 1 Hits: ', $hit[0];
echo 'Type 2 Hits: ', $hit[1];
echo 'Type 3 Hits: ', $hit[2];
echo 'Type 4 Hits: ', $hit[3];
echo 'Type 5 Hits: ', $hit[4];
If you need to update all members, you can wrap all of that into a loop that loops through each member id.

mysql 2 tables updation/deletion based on condition

Hello friends I have 2 Mysql tables with 1:N relationship between category and category_Dates
Category:
ID Category Frequency
1 Cat A Half-yearly
2 Cat B Quarterly
category_Dates:
ID CatID Date
1 1 01-Jan-15
2 1 01-Jul-15
3 2 01-Jan-15
4 2 01-Apr-15
5 2 01-Jul-15
6 2 01-Oct-15
based on the category frequency I am entering number of records automatically in category_date. Eg
When category frequency = quarterly, I am entering 4 records in category_date with ID of that category. And dates will be entered later.
I am little confused if in case on wants to edit the frequency from halfyearly to yearly. How to change number of records. Please help with your valuable suggestions. I am using laravel 4 framework with mysql
best way would be with 3rd table joining Dates and Categories. See little carefully ,you can see its actually Many to Many relationship (N to N) as 1 category can have multiple dates. and one date may be part of multiple categories, like say 01-Jan-15 is part of Category 1 and 2 as well.
So use
category table
id Category Frequency
1 Cat A Half-yearly
2 Cat B Quarterly
date table
id Date
1 01-Jan-15
2 01-Apr-15
3 01-Jul-15
4 01-Oct-15
categories_dates table
ID CatID Date_id
1 1 1
2 1 3
3 2 1
4 2 2
5 2 3
6 2 4
If you change the frequency in Category table, retrieve the update category_id,
delete all from category_dates where CatId=category_id then insert the new entries in category_Dates.
Hope this help.
I assume your models are Category and CategoryDates.
let's update category id 1 from Half-yearlyto to Quarterly
$query = Category::find(1);
$query -> Frequency = 'Quarterly';
$query -> save();
return $query -> id;
in the CategoryDates model you would delete the catID = 1 and insert new data
$catID = 1;
$query = CategoryModel::where('CatId',$catId) -> delete();
$data = ['CatId' => $catID,'date' => 01-Jan-15, ....];
CategoryModel::create($data);
of course assuming that you would return the newly updated category id to your controller and call a funtionn to do the update in your CategoryModel.
Hope this help.

php pdo copy column between tables

I got the two tables(Table1 and Table2):
Table1:
id hits url
1 11 a
2 5 b
3 6 c
4 99 d
5 14 e
Table2:
id url 2014.04.13 2014.04.14
1 a 0 5
2 b 0 1
3 c 0 3
4 d 0 60
5 e 0 10
hi all,
Table1 one contains the actual hits(which are always up-to-date) and Table2 to statistics(which are done every day at midnight). The columns id(unique number) and url are in both tables the same. So they got the same amount of rows.
So i create every day a new column(with the date of today) and copy the column hits from the table 'Table1' into the new created column into the table 'Table2'
First i alter Table2:
$st = $pdo->prepare("ALTER TABLE Table2 ADD `$today_date` INT(4) NOT NULL");
$st->execute();
Then i cache all entries i need from Table1:
$c = 0;
$id = array();
$hits = array();
$sql = "SELECT id, hits FROM Table1 ORDER BY id ASC";
$stmt = $pdo->query($sql);
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$id[$c] = $row['id'];
$hits[$c] = $row['hits'];
$c++;
}
At last i update Table2:
for ($d = 0 ; $d < $c ; $d++)
{
$id_insert = $id[$d];
$sql = "UPDATE DOWNLOADS_TEST SET `$datum_det_dwnloads`=? WHERE id=?";
$q = $pdo->prepare($sql);
$q->execute(array($hits[$d], $id[$d]));
if($q->rowCount() == 1 or $hits[$d] == 0) // success
$hits[$d] = 0;
else // error inserting (e.g. index not found)
$d_error = 1; // error :( //
}
So what i need is to copy(insert) a column from one table to another.
The two tables are having ~2000 elements and the copying as described above takes around 40 sec. The bottleneck is the last part (inserting into the Table2) as i found out.
One thing i found is to do multiple updates in one query. Is there anything i can do besides that?
I hope you realise that at some point your table will have irrational number of columns and will be highly inefficent. I strongly advise you to use other solution, for example another table that holds data for each row for each day.
Let's say you have a table with 2000 rows and two columns: ID and URL. Now you want to know the count of hits for each URL so you add column HITS. But then you realise you will need to know the count of hits for each URL for every date, so your best bet is to split the tables. At this moment you have one table:
Table A (A_ID, URL, HITS)
Now remove HITS from Table A and create Table B with ID and HITS attributes). Now you have:
Table A (A_ID, URL)
Table B (B_ID, HITS)
Next move is to connect those two tables:
Table A (A_ID, URL)
Table B (B_ID, A_ID, HITS)
Where A_ID is foreign key to attribute "A_ID" of Table A. In the end it's the same as first step. But now it's easy to add date attribute to Table B:
Table A (A_ID, URL)
Table B (B_ID, A_ID, HITS, DATE)
And you have your solution for database structure. You will have a lot of entries in table B, but it's still better than a lot of columns. Example of how it would look like:
Table A | A_ID | URL
0 index
1 contact
Table B | B_ID | A_ID | HITS | DATE
0 0 23 12.04.2013
1 1 12 12.04.2013
2 0 219 13.04.2013
3 1 99 13.04.2013
You can also make unique index of A_ID and DATE in Table B, but I prefer to work on IDs even on linking tables.

Categories