Join column names from Tab1 with 1 column values of Tab2 - php

I have 2 tables with the following structures:
// tab1:
| ID | Col1 | Col2 | Col3 | Col4 |
|----|------|------|------|------|
| 1 | Val1 | Val2 | Val3 | Val4 |
| 2 | Val5 | Val6 | Val7 | Val8 |
// tab2:
| Name |
|------|
| Col1 |
| Col3 |
I now need to get all values from tab1 and somehow join them with the values of the column of tab2, so that in the frontend all columns from tab1, that are also present in tab2, are bold.
In pseudocode it would look like that:
SELECT Col1, COl2, Col3, Col4 FROM tab1, tab2 WHERE ID=1 AND {possibly a left join on tab2}
The desired output as a table in the fronted could be:
Value 1: Val1
Value 2: Val2
Value 3: Val3
Value 4: Val4
Since col1 and col3 are also in tab2, their values should be bold.
So I just need the appropriate query with a "flag". In the frontend I then would just loop the results and look for the flag. If the flag is set, display the value as bold.
I don't really have influence on the database structure.

Assuming that the table structure is complete and we know all the column names, we can execute the below query to check whether a value exists or not.
select col1 as col1 ,
(select count(*) from tab2 where name = 'col1') col1_exists,
col2 as col2,
(select count(*) from tab2 where name = 'col2') col2_exists,
col3 as col3 ,
(select count(*) from tab2 where name = 'col1') col3_exists
from tab1;
For non zero 'exists' values, we can show the corresponding column value in bold. Here is the SQL Fiddle.

Try this :
SELECT
t.`VALUE`,
(CASE WHEN tab2.Name IS NULL THEN 0 ELSE 1 END) flag
FROM
(
SELECT
Col1 AS `VALUE`,
'Col1' AS colNum
FROM tab1
WHERE ID = 1
UNION
SELECT
Col2 AS `VALUE`,
'Col2' AS colNum
FROM tab1
WHERE ID = 1
UNION
SELECT
Col3 AS `VALUE`,
'Col3' AS colNum
FROM tab1
WHERE ID = 1
UNION
SELECT
Col4 AS `VALUE`,
'Col4' AS colNum
FROM tab1
WHERE ID = 1
) t
LEFT JOIN tab2
ON tab2.`Name` = t.colNum;
SQL FIDDLE

Due to the restrictions with your design, you are not able to do this with MYSQL alone, but you can with the help of PHP:
get the column names from tbl2
use those column names to obtain your results from tbl1
Try the following (assuming you use mysqli):
//get columns from tbl2
$sql = 'SELECT * FROM tbl2';
$result = mysqli_query($conn, $sql);
$cols = [];
while ($row = mysqli_fetch_assoc($result)) {
$cols[] = $row['name'];
}
//get results from tbl1 using column names
$sql = 'SELECT ' . implode(',', $cols) . ' FROM tbl1 WHERE ID=1';
$result = mysqli_query($conn, $sql);
while ($row = mysqli_fetch_assoc($result)) {
var_dump($row);
}

Related

Fetch SQL data from same table of different column

I'm using get request to fetch serial and put it into query.
$id = $_GET['id'];
$select = $pdo->prepare("SELECT * FROM tbl_product WHERE serial='.$id.'");
$select->execute();
while($row = $select->fetch(PDO::FETCH_OBJ)){
echo '
<tr>
<td>'.$row->pname.'</td>
<td>'.$row->pcategory.'</td>
<td>'.$row->serial.'</td>
<td>'.$row->sku.'</td>
';
}
My table look like this, I tried using inner join for same table but it didn't work.
When user key in serial through get request localhost?id=12345678 . I want it to show item1 - item3, that match with its SKU
id | sku | serial | product_name
0 | ABC | 12345678 | item1
1 | ABC | 87654321 | item2
2 | ABC | 23456789 | item3
3 | DEF | 56789234 | item4
Something like
select * from tbl_product where sku = (select sku from tbl_product where serial = :serial)
might do it, presuming a PDO prepared statement.
You can try inner join like this:
select id, c.sku, serial, product_name from table_name t
inner join (
select sku from table_name where serial ='12345678'
)c on t.sku = c.sku
in your code:
$id = $_GET['id'];
$query = "select id, c.sku, serial, product_name from table_name t
inner join (
select sku from table_name where serial = :serial
)c on t.sku = c.sku";
$select = $pdo->prepare($query);
$select->bindParam(':serial', $id);
$select->execute();
while($row = $select->fetch(PDO::FETCH_OBJ)){
echo '
<tr>
<td>'.$row->pname.'</td>
<td>'.$row->pcategory.'</td>
<td>'.$row->serial.'</td>
<td>'.$row->sku.'</td>
';
}
Don't trust any input, use prepare, and bindParam to avoid SQL injection. You can reference SQL injection here https://www.php.net/manual/en/security.database.sql-injection.php
Self join
$select = $pdo->prepare("SELECT * FROM tbl_product P1 LEFT JOIN tbl_product P2 ON P2.sku = P1.sku WHERE P1.serial='.$id.'")

Finding duplicate records in table along with its related other duplicate

I'm trying to find duplicate records in my table and I have the code to show the records but I need to modify it so that it also shows the other duplicate record. My example table is the following:
TABLE IMAGE
As you can see, the table (t_sen) contains duplicate records and I have this code to display the duplicate records:
$sql = "SELECT ID, PARA_NUMBER, TEXT FROM t_sen GROUP BY TEXT having count(*) >= 2";
$results = mysqli_query($conn, $sql) or die(mysqli_error());
while($row = mysqli_fetch_assoc($results)){
foreach($row as $column => $value){
print "$column: $value <br>";
}
print "<br>";
}
The output that I get is:
ID | PARA_NUMBER | TEXT
----------------------------
3 | 1 | is
7 | 2 | live
However the output that I want is:
ID | PARA_NUMBER | TEXT
----------------------------
3 | 1 | is
4 | 1 | is
7 | 2 | live
8 | 2 | live
I want it to show the other duplicate column also within the defined PARA_NUMBER. So an example (made up?) query would be something like:
SELECT ID, PARA_NUMBER, TEXT FROM t_sen (WITHIN PARA_NUMBER = 1) having count(*) >= 2
So the output should be:
ID | PARA_NUMBER | TEXT
----------------------------
3 | 1 | is
4 | 1 | is
But it would be much better if I don't have to repeat the query for every single PARA_NUMBER as there are many numbers and just one query can display all the duplicate records.
Hope I'm clear. Any help would be much appreciated.
This query will do what you want. It uses a subquery to find all the values of TEXT which have duplicates in the table, and JOINs that to the original table so that you can display each entry which has the duplicate TEXT value.
SELECT ID, PARA_NUMBER, t1.TEXT FROM
t_sen t1
JOIN (SELECT TEXT
FROM t_sen
GROUP BY TEXT
HAVING COUNT(*) >= 2) t2
ON t1.TEXT = t2.TEXT
Output:
ID PARA_NUMBER TEXT
3 1 is
4 1 is
7 2 live
8 2 live
SQLFiddle Demo
If you only want to get the duplicates in PARA_NUMBER 1, for example, just add a WHERE clause to the end:
SELECT ID, PARA_NUMBER, t1.TEXT FROM
t_sen t1
JOIN (SELECT TEXT
FROM t_sen
GROUP BY TEXT
HAVING COUNT(*) >= 2) t2
ON t1.TEXT = t2.TEXT
WHERE PARA_NUMBER = 1
Output:
ID PARA_NUMBER TEXT
3 1 is
4 1 is
Edit
Based on OPs requirement to be able to edit the rows in phpMyAdmin, a query with a JOIN will not solve the problem. Instead a query such as this one is required:
SELECT ID, PARA_NUMBER, t1.TEXT FROM
t_sen t1
WHERE EXISTS (SELECT *
FROM t_sen t2
WHERE t2.PARA_NUMBER = t1.PARA_NUMBER AND
t2.TEXT = t1.TEXT AND
t2.ID != t1.ID)
Output:
ID PARA_NUMBER TEXT
3 1 is
4 1 is
7 2 live
8 2 live
I always use grouping to find duplicates. My suggestion:
SELECT GROUP_CONCAT(CONCAT_WS('-', ID, PARA_NUMBER, TEXT)) AS data FROM t_sen GROUP BY PARA_NUMBER HAVING COUNT(*) > 2
This will give you results in this format:
| data |
| 3-1-is,4-1-is |
SELECT t.ID, t.PARA_NUMBER, t.TEXT FROM
(SELECT TEXT FROM t_sen GROUP BY TEXT having count(*) >= 2) as duplicateValue
LEFT JOIN t_sen as t on duplicateValue.TEXT = t.TEXT
WHERE 1;
Left Join
SELECT
t1.*
FROM
t_sen AS t1
LEFT JOIN
t_sen AS t2 ON t1.ID != t2.ID AND t1.PARA_NUMBER = t2.PARA_NUMBER
WHERE
t2.ID IS NOT NULL
Fiddle
t1.ID != t2.ID excludes matching the same row in both tables (well both sides of the join)
t1.PARA_NUMBER = t2.PARA_NUMBER joins the tales on the duplicate number
WHERE t2.ID IS NOT NULL excludes records that are not duplicate.
you could also use TEXT which is a really bad name for a column, by adding that to the ON part of the join, in addition or in place of PARA_NUMBER as you needs require.
Just for posterity
CREATE TABLE t_sen (
ID INT,
PARA_NUMBER INT,
`TEXT` VARCHAR(20)
);
#non duplate
INSERT INTO t_sen (ID, PARA_NUMBER, `TEXT`)VALUES(1,10,'the');
#duplicates
INSERT INTO t_sen (ID, PARA_NUMBER, `TEXT`)VALUES(3,1,'is');
INSERT INTO t_sen (ID, PARA_NUMBER, `TEXT`)VALUES(4,1,'is');
INSERT INTO t_sen (ID, PARA_NUMBER, `TEXT`)VALUES(7,2,'live');
INSERT INTO t_sen (ID, PARA_NUMBER, `TEXT`)VALUES(8,2,'live');
Below query should print all the records that have duplicate on PARA_NUMBER and TEXT field-
SELECT ID, PARA_NUMBER, TEXT FROM t_sen WHERE (PARA_NUMBER, TEXT) IN
(SELECT PARA_NUMBER, TEXT FROM t_sen GROUP BY PARA_NUMBER, TEXT having count(*) >= 2)

Update two table row from a post value

I have here two tables, I need to update both table row field from a post value. table1.item and table2.item update from post value. I didn't know how to set both table field equal to post value.
Any help will appreciate.
Table1
| pr_id | item |
----------------
| 1001 | pen |
Table2
| pr_id | item |
----------------
| 1001 | pen |
Query
<?php
$pr = $mysqli->real_escape_string($_POST["pr_id"]);
$item= $mysqli->real_escape_string($_POST["item"]);
$mysqli->query("UPDATE table1 LEFT JOIN table2 ON table1.pr_id = table2.pr_id WHERE table1 .pr_id = '$pr' ");
?>
Try this:
update table1 inner join table2
on table1.pr_id=table2.pr_id
//your changes
set table1.item ='some thing', table2.item ='some thing'
where table2 .pr_id ='$pr' ;
Try this:
Query:
UPDATE table1 T1 LEFT JOIN
table2 T2 ON T1.pr_id = T2.pr_id
SET T1.Item= '$item', T2.Item = '$item'
WHERE T1.pr_id = '$pr'
With php:
$mysqli->query("UPDATE table1 T1 LEFT JOIN table2 T2 ON T1.pr_id = T2.pr_id SET T1.Item= '$item', T2.Item = '$item' WHERE T1.pr_id = '$pr' ");
According to my opinion it is better to use Compound Trigger for updating 2 diffenent tables at the same time. Try to use that.

Selecting values present in one column but not in all other columns

Suppose I have columns col1, col2, col3, col4 in myTable and I need to print out the values exclusive to only one column .
So if the above looks like
col1 col2 col3 col4
s e c b
c c a s
n s e a
d d q c
Then the output should be n, q b since they are exclusive only to col1, col3 and col4 respectively.
How can I achieve this through a query in mysql php?
EDIT The duplicates dont have to be in a single row .I have changed the the table layout now to make it clear.
If you are looking for a SQL-only solution, you can do a query per column like this:
SELECT
col1 AS unique_on_col1
FROM table
WHERE col1 NOT IN (SELECT col2 FROM table)
AND col1 NOT IN (SELECT col3 FROM table)
AND col1 NOT IN (SELECT col4 FROM table)
It's possible to combine all four queries with UNION but that may not be necessary depending on what you want to do with the data. Also, this query should not perform very well with large datasets.
One slightly more compact way of getting all of them at once:
select distinct col1
from myTable
where col1 not in (select a.col1
from myTable a join myTable b
on a.col1 = b.col2 or a.col1=b.col3 or a.col1=b.col4)
union
select distinct col2
from myTable
where col2 not in (select a.col2
from myTable a join myTable b
on a.col2 = b.col1 or a.col2=b.col3 or a.col2=b.col4)
union
select distinct col3
from myTable
where col3 not in (select a.col3
from myTable a join myTable b
on a.col3 = b.col1 or a.col3=b.col2 or a.col3=b.col4)
union
select distinct col4
from myTable
where col4 not in (select a.col4
from myTable a join myTable b
on a.col4 = b.col1 or a.col4=b.col2 or a.col4=b.col3)
$sql = "
SELECT DISTINCT 'col1' as descr,col1 as val FROM myTable
UNION
SELECT DISTINCT 'col2' as descr,col2 as val FROM myTable
UNION
SELECT DISTINCT 'col3' as descr,year as val FROM myTable";
$result = #mysql_query($sql, $con) or die(mysql_error());
while($row = mysql_fetch_array($result)) {
$make_array[$row['descr']][]=$row['val'];
}
I'm guessing this should work. Dint try the code out but give this one a shot and let us know.
Try This:
SELECT col1 AS unique_on_col1
FROM table
WHERE col1 NOT IN (SELECT col2 FROM table)
AND col1 NOT IN (SELECT col3 FROM table)
AND col1 NOT IN (SELECT col4 FROM table)

Check distinct value ignoring other columns data

If I have a table with data like this :
Col1 | Col2 | Col3
111 | a |
222 | b | 1
111 | |
And I wish to select Distinct Col1 only from my temporary table then insert into another table.But with the table above , the second "111" will be selected as well since it has different Col2 data.
Or if I select Distinct Col1 only , the other columns data will be ignored...
So is there any way to solve this problem? I wish to choose only the first inserted row of same Col1 data.
I'm using this query:
mysql_query("INSERT DELAYED INTO Tableb (Col1,Col2,Col3) SELECT DISTINCT Col1,Col2,Col3 FROM TempTable");
Thanks for any reply.
PS: I'm not sure how to specified the title according to my question...perhaps someone can help me.
Maybe something like this (this is probably what you want):
INSERT INTO Tableb
(
Col1,Col2,Col3
)
SELECT
t.Col1,
MAX(t.Col2) AS Col2,
MAX(t.Col3) AS Col3
FROM
TempTable as t
GROUP BY
t.Col1
Or if you want the MIN value. Like this:
INSERT INTO Tableb
(
Col1,Col2,Col3
)
SELECT
t.Col1,
MIN(t.Col2) AS Col2,
MIN(t.Col3) AS Col3
FROM
TempTable as t
GROUP BY
t.Col1
First you need to determine last ID per distinct value of col1, and then you select rows containing this id:
INSERT DELAYED INTO Tableb (Col1,Col2,Col3)
SELECT TempTable.Col1, TempTable.Col2, TempTable.Col3
from TempTable
inner join
(
select Col1, max(ID) ID
from TempTable
group by Col1
) c
ON TempTable.ID = c.ID
Inner query returns ID's to be inserted, so one simply joins them to original table to filter the table.
Substitute max(id) with min(id) if you want first inserted TempTable record.
mysql_query("INSERT DELAYED INTO Tableb (Col1,Col2,Col3) SELECT Col1, MAX(t.Col2) AS Col2, MAX(t.Col3) AS Col3 FROM TempTable GROUP BY Col1");
INSERT DELAYED INTO Tableb (Col1,Col2,Col3) SELECT Col1,Col2,Col3 FROM TempTable GROUP BY Col1 ORDER BY [your way of sorting here]
Does that do it?

Categories