Combine Single Column Data into Double Column Data in php - php

I have 600 rows of data in one table and table structure is,
Table Name: city_Data
------------------------------
cityId | cityName
------------------------------
1 | chennai
2 | madurai
3 | trichy
4 | kovai
...
...
...
------------------------------
cityId - autoincrement
now i would like to mix this table data and inset into another table. this table's name is city_Mix.
---------------------------------------
mixId | city1 | city2
---------------------------------------
1 | chennai | madurai
2 | chennai | trichy
3 | chennai | kovai
4 | madurai | chennai
5 | madurai | trichy
6 | madurai | kovai
7 | trichy | chennai
...
...
...
---------------------------------------
here, city1 and city2 are should not be same and mixId - autoincrement
how to do this? anyone plz help me with sample code..

try the following query, which uses join to combine the city names which dont match and insert the dat to city_mix table
INSERT INTO city_mix
(city1,city2) select t1.cityName,t2.cityName from Table1 t1 join Table1 t2 on t1.cityName != t2.cityName;
http://sqlfiddle.com/#!9/2e01ea/3

I'm making some assumptions about what you are specifically asking, if you were to supply a little more information it might help:
Does city_Mix already contain the field city2 or is that the column you wish to join from city_Data?
Are you doing this in PHP or SQL?
Is city_Mix really a self-iteration of the city_Data table?
Is the data you've presented representational of a database table, or a PHP data structure?
Once again, I am making some assumptions here, but I'll try to help based on what you've provided...
It appears that city_Mix matches #3 from my question list (so you want to take a list of items, and for each item in the list, map it to all other items on the list). If this assumption is correct, here is one way to approach the solution:
Using SQL
// You'll probably want to use an INNER JOIN to accomplish this quickly, something like the following
(SELECT 'cityName' FROM `city_Data` c INNER_JOIN `city_Data` m ON m.cityName != c.cityName)
Using PHP
FYI: I would recommend against this in favor of doing this with SQL, but wanted to provide it as "a way to do it" since you did not indicate which way you were approaching the solution.
<?php
$cityMixData = []; //Final data table as you've indicated you desire
//Connect to your database
$con = mysql_connect("localhost","inmoti6_myuser","mypassword");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("databaseName", $con);
// Define our SQL query
$query = "SELECT DISTINCT `cityName` FROM `city_Data` ORDER BY `cityId`";
// Execute the query
$cities = mysql_query($query);
$i = 1; // Iterator index
$cityMixData = [];
// Loop through the list of unique city names and map all other items accordingly
while( $city = mysql_fetch_array( $cities, MYSQL_ASSOC ) ) {
$tmpArr = $cities;
unset($tmpArr[$row[$i - 1]); // Remove self
$cityMap = array_values($tmpArr); // reindex array
$mixRow = array($mixId => $i, $city1 => $city['cityName'], $city2 => $cityMap); // Create a row with auto-increment ID, city1 === unique city name, city2 === list of unique cities sans-city1
$cityMixData[] = $mixRow; // Add row to cityMixData which is multi-dimensional array
$i++; // Increment iterator
}
// Connect to DB
// Create city_Mix table if not exist
// Appropriately generate SQL based on $cityMixData structure, might get messy
// Save to DB
?>
If you answer the questions I posed above, I will be able to help more.

Related

Count number of family members from one table for each rows in another table called house?

I have two MySQL tables, first, is house and second one family, The house table has two columns called house_id and house_name while the second table has three columns family_id, member_name the last column in the family table used to reference house_id from first table this is house_id
CONCEPT:
How can get number of family_members with/who come from a certain house and put the counted number in the HTML table by fetching only on house table?
I created the following script to fetch from house,
SELECT * FROM house;
And I manipulated the fetched data using foreach like this,
$mystmt = $db -> prepare('SELECT * FROM house');
$mystmt->execute();
$myresult = $mystmt->fetchAll();
foreach($myresult as $mydata) {
$myarray = array();
$myarray[] = $mydata['house_id'];
$myarray[] = $mydata['house_name'];
$output[] = $myarray;
}
echo json_encode($output);
On the above code i get only two columns the house_id and house_name, Now how can i adjust this code to count from family table so that I can get another column called total_family_members
Just like this
family_id | member_name | house_id
1 | John Jackson | 1
2 | Ketty Bebe | 2
3 | Maam Juke | 1
4 | Tike Nuke | 2
5 | Carol Michael | 2
Desired result
house_id | house_name | total_family_members
1 | Joh's house| 2
2 | kim's house| 3
In your example, two different processes are involved:
Link everyone's house id to the house name. This can be achieved with a JOIN.
Count the number of people in each house. This can be achieved with a GROUP BY and a COUNT.
Here is a solution:
SELECT house.house_id , house.house_name , COUNT( * ) AS total_family_members
FROM house
INNER JOIN family ON family.house_id = house.house_id
GROUP BY family.house_id

How to fill an intermediate table?

I have Two tables in ManyToMany relation:
Table Molécules:
id | main_name | others …
--- | --------- | ------
1 | caféine | others …
Table jsonTextMining:
id | title | molecule_name | others …
---|------- |-------------------------------------|------
1 | title1 | colchicine, cellulose, acid, caféine| others …
and 1 intermediate table:
Table json_text_mining_molecule (it's an exemple i don't succeed to fill it):
json_text_mining_id | molecule_id
------------------------ | ---------------
1 | corresponding molecule id's
1 | corresponding molecule id's
2 | corresponding molecule id's
My problem is that molecule_name in jsonTextMining are a string, i need to separate them before anything.
I tried this :
$molecules = explode (', ', $jsonTextMining→getMoleculeName());
foreach ($molecules as $molecule) {
$jsonTextMining->setMolecule($molecule);
}
$em->persist($jsonTextMining);
$em->flush;
But i think i should loop on jsonTexMining too and to be honnest i'm not sure where to put this part of code. Is it on a random page and the code will execute, should i do a button ?
I know exactly how to fill table with id's when there is a OneToMany relation, i use sql like this :
UPDATE table1 SET id_relation1 = table2.id
FROM table2
WHERE table1.main_name = table2.main_name
But this code fill only one column with id and there's always the matter of string. Is there really a way to get these id's linked so every molecule will have several jsonTextMining ?
You can first split the string using regexp_split function:
select id, regexp_split_to_table(molecule_name,', ') as m_name from jsonTextMining
That will give you a table of ids and names:
id | name
----+------------
1 | acid
1 | caffeine
1 | cellulose
1 | colchicine
Next, you can read from the above, match the names to the ids in the molecule table and aggregate the ids. All put together would result in this:
select s.id, string_agg(m.id::text, ', ')
from (select id, regexp_split_to_table(molecule_name,', ') as m_name
from jsonTextMining) as s, molecules m
where m.main_name = s.m_name group by s.id;
Which gives this result:
id | string_agg
----+------------
1 | 4, 1, 3, 2
(1 row)
If you don't want to aggregate the results and display them one row per molecule then just get rid of string_agg and the group by:
select s.id, m.id
from (select id, regexp_split_to_table(molecule_name,', ') as m_name
from jsonTextMining) as s, molecules m
where m.main_name = s.m_name;

Yii2: ActiveRecord with distinct query

I need to write an ActiveRecord query where I get all fields of rows without duplicates in one field.
Example: Here is a table of books. I want to get all data of the rows with
distinct isbn. From duplicates the first row should be taken. The result should be the rows with id 1,2,4
id | title | isbn
--- | ------- | ------
1 | hello | 1001
2 | world | 1002
3 | this | 1002
4 | is | 1003
5 | funny | 1003
My first attempt was
$books = Books::find()->select('isbn')->distinct()->all();
but that fills only the isbn field in $books[0], $books[1], ....
Is this possible using Yii2 ActiveRecord?
You may use groupBy() for this:
$books = Books::find()->groupBy(['isbn'])->all();
But this returns random row with matching isbn value and may not work in some DBMS. Your requirements are too ambiguous to handle it in predictable way. But if you want always first row, you may use subquery to fetch matching isbn and id:
$query = (new Query())
->select(['MIN(id) as id, isbn'])
->from(Books::tableName())
->groupBy(['isbn']);
return Books::find()
->alias('book')
->innerJoin(['subquery' => $query], 'book.id = subquery.id AND book.id = subquery.id')
->all();
The description given in Yii2 for the distinct property is as follows:
Whether to select distinct rows of data only. If this is set true, the SELECT clause would be changed to SELECT DISTINCT.
-- https://www.yiiframework.com/doc/api/2.0/yii-db-query#$distinct-detail
therefore you should pass true with distinct property if you need to select the distinct values of 'isbn' as follows:
$books = Books::find()->select('isbn')->distinct(true)->all();

Strip comma separated value

I am using PHP and MySQL database
I Have a table which has a column: actors
In a row in the table, in the actors column, there maybe several actors listed e.g. Denzel Washington, Charlie Sheen, Matt Damon
The next row might be: Matt Damon, Robert De Niro, Denzel Washington
They are always comma seperated.
I have an autocomplete where I am asking the user to choose an actor. So, when the autocomplete looks in the column, it returns the whole column value.
e.g. someone searching for Denzel will get in their autocomplete results:
Denzel Washington, Charlie Sheen, Matt Damon
Matt Damon, Robert De Niro, Denzel Washington
As far as I know there's no way to seperate this at that level so I'm thinking I might have to strip out the actors from that table, into a seperate table which just services the autocomplete.
Is this the best way to do it and if so, can it be done? Is there a simple SQL query i could use to get the actors out, seperately, then load another table. This is constantly updated data so needs to run every day but I presume if I had the actor column in a new table as unique then i wouldn't have duplicates.
Or is there a more efficient way?
NOTE: I need to point out that this is a XML feed and I have no control over the data - yes, I know it should all be seperate from the get go but unfortunately I'm just working with what I have
What you need is something like this
table actors
id | name
table actor_entries
id | data_id | actor_id
table data
id | <other columns>
Then your data would like something like this
table actors
1 | Denzel Washington
2 | Charlie Sheen
3 | Robert De Niro
table data
1 | some data // this row is associated with actors 1 and 2
2 | some data // this row is associated with actors 2 and 3
table actor_entries ( id | data_id | actor_id )
1 | 1 | 1
2 | 1 | 2
3 | 2 | 2
4 | 2 | 3
What you should have had is three different tables:
Movies Actors MovieActors
---- ---- ----------
movie_id PK actor_id PK movie_id FK
title name actor_id FK
year born
gender
Then you would not have that huge mess. Also you would be able to search data
SELECT Actors.name FROM Actors WHERE Actors.name LIKE '%Pam' LIMIT 5
Or get all movies where actor has participated:
SELECT
Movies.title
FROM Movies
LEFT JOIN MovieActors USING(movie_id)
LEFT JOIN Actors USING(actor_id)
WHERE
Actors.name = 'Foo Bar'
AND Movies.year > 1990
If you already know the basics of SQL, i would suggest for you to read SQL Antipatterns. That book covers this an many other issues.
This is probably not a very good way to store data since it would become very slow and difficult to maintain once the csv reaches a certain size.
Anyway, as for your question, let me know if this helps:
<?php
$search = $_GET['search']; // assume it's 'de'
$result = array(); // this contains the result
$sql = 'SELECT `actors` from `tablename`;';
$run = mysql_query( $sql );
if ( $run && mysql_num_rows( $run ) ) {
while ( ( $data = mysql_fetch_assoc( $run ) ) !== FALSE) {
$num = explode( ',', $data[ 'actors' ] );
for ($i=0; $i < $num; $i++) {
if( stripos( $data[ $i ], $search ) !== false ) {
$result[] = trim( $data[ $i ] );
}
}
}
}
// here's the result you want
$result = array_values( array_unique( $result ) );
?>
This will work, but again, as many have suggested, this is not a very good choice.
You can use the php explode function with ',' as separator. It will return an array with all
actor name

How to check of the last 2 entries of a mysql query in various column have the same value?

i have a table link with a structure like this
spreader | host1 | host2 | host 3 | id | datetime |
---------------------------------
expl.com | 1 | 5 | 2
what.de | 1 | 5 | 2
expl.com | 1 | 2 | 3
what.de | 2 | 5 | 5
How to check if the last 2 entry with the same spreader have the same values in host1, host2, host3 ...
For this example it sould give me
expl.com => host1 = 1
what.de => host2 = 5
I maybe know a way but i would have to have 10 sql querys one for each host. Do you know a efficient way to do this in php after i just get the entire date from the database with just one query?
Well i got this now it fires out 10 mysql querys i would love to see how to make this better:
global $hosters;
global $filespreader_names;
foreach ( $filespreader_names as $filespreader ) {
$feedtable = feedback_tabelle_holen(" WHERE filespreader='$filespreader' ORDER BY aktualisiert DESC LIMIT 2");
//var_dump($feedtable);
foreach ( $hosters as $host ) {
if ( ( $feedtable[0][$host] == $feedtable[1][$host] ) && ( $feedtable[0][$host] != 0 ) ) {
echo "<br />$filespreader -> $host = " . $feedtable[0][$host];
}
}
}
the globals i get in are just arrays with all the spreaders and host names i need
You might be able to do an Inner Join to produce matching records. If the gloabals you get in are from another table an inner join will give you a recordset with all the matching records that you could manipulate from there but it would only be one query.
If this is TableA on the left and TableB on the right.
id name id name
-- ---- -- ----
1 Pirate 1 Rutabaga
2 Monkey 2 Pirate
3 Ninja 3 Darth Vader
4 Spaghetti 4 Ninja
SELECT * FROM TableA
INNER JOIN TableB
ON TableA.name = TableB.name
That query will result in rows of the matching data according to your query
id name id name
-- ---- -- ----
1 Pirate 2 Pirate
3 Ninja 4 Ninja
I don't know if that helps at all but I wasn't really clear on your structure and exactly what you wanted. If the globals are session variables and not stored in a table this answer probably won't help you.
If you want to use joins check out http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html

Categories