I have two tables with the same structure. (refer below)
records = id (int, auto increment), name (varchar 250), age (int), address (varchar 250)
backup = id (int), name (varchar 250), age (int), address (varchar 250)
both table contents 3 records. Now, I want to compare those two tables per row by per column of the row and if there's a row that didnt match to the corresponding row on the compared table then produce and error.
table "records" content:
row 1 : column id = 1, column name = name1, column age = 12, column address = USA
row 2 : column id = 2, column name = name2, column age = 17, column address = USA
row 3 : column id = 3, column name = name3, column age = 32, column address = USA
table "backup" content:
row 1 : column id = 1, column name = name1change, column age = 12, column address = USA
row 2 : column id = 2, column name = name2, column age = 17, column address = USA
row 3 : column id = 3, column name = name3, column age = 32, column address = USA
as you can see from the above table contents, in the table "backup row 1, column name" there is a changes, name1 (records table) is changed to name1change (backup table). So when the row 1 of table records is compare to row 1 of table backup and found a difference, it will then get the row number and column name followed by a text of error (refer below)
echo $errorRow . "with" . $errorColumnOfTheErrorRow . "didn't match, there's is changes";
and I want to loop until the end of records with the same process (compare). How to make it? any ideas, help, suggestions and recommendation would be gladly appreciated. Thank you!
so far, what i tried is (refer below)
$sql = "SELECT DISTINCT * FROM (SELECT a.* FROM records a UNION SELECT b.* FROM backup b ) c";
$result = mysqli_query($this->db,$sql);
$sql = "SELECT COUNT(*), id FROM (SELECT DISTINCT * FROM (SELECT a.* FROM records a UNION SELECT b.* FROM backup b ) c ) d GROUP BY id;";
$result = mysqli_query($this->db,$sql);
echo $result;
as above query, im trying to display the unmatched row but sadly, not working.
You can do this is SQL in a nice way:
First step: put all the data together and keep only the distinct (=not the same) rows:
SELECT DISTINCT *
FROM (
SELECT a.*
FROM records a
UNION
SELECT b.*
FROM backup b ) c
Second step:
Count all records where ID occurs more then 1 time:
SELECT COUNT(*), id
FROM (
SELECT DISTINCT *
FROM (
SELECT a.*
FROM records a
UNION
SELECT b.*
FROM backup b ) c ) d
GROUP BY id
HAVING COUNT(*)>1;
This will give you the exact ids where the rows are not the same.
Third step:
Get you the rows with the changed data:
SELECT * FROM (
SELECT "current data" AS description,f.* FROM
records f
INNER JOIN (
SELECT id
FROM (
SELECT DISTINCT *
FROM (
SELECT a.*
FROM records a
UNION
SELECT b.*
FROM backup b ) c ) d
GROUP BY id
HAVING COUNT(*)>1 ) e ON f.id=e.id
UNION
SELECT "backup data" AS description, g.* FROM
records g
INNER JOIN (
SELECT id
FROM (
SELECT DISTINCT *
FROM (
SELECT a.*
FROM records a
UNION
SELECT b.*
FROM backup b ) c ) d
GROUP BY id
HAVING COUNT(*)>1 ) h ON g.id=h.id;
) i ORDER BY id ASC, description ASC;
It is not pretty, but it works :)
Related
I am having 2 tables :
1.internal_employee_master
id employee_name unique_id
1 Noah ABCD
2 Liam ABCD
3 William ABCD
4 Benjamin ABCD
5 Jacob EFGH
2.external_employee_master
id name unique_id
1 Elijah ABCD
2 Ethan ABCD
3 Alexander EFGH
I am using UNION query to get both tables data into single table and display this data into html table.
select id
, employee_name
, unique_id
from internal_employee_master
where unique_id = 'ABCD'
union
select id
, employee_name
, unique_id
from external_employee_master
where unique_id = 'ABCD'
I want to store payslips of both employees into single table.
I have one table payslips with emp_id and emp_type columns.
I am storing data into payslips data like:
id pay_slip emp_id emp_type
1 Noah_payslip.pdf 1 internal
2 Liam_payslip.pdf 2 internal
3 Lia_payslip.pdf 1 External
as you can see in above table i am storing emp_id and emp_type of
both the tables in single columns each.
Now, i dont undestand how to split data of internal employee and
external employee from pay_slip table and show data in html table.
Currently, i am writing below sql joins to get employee_names of
internal and external employee tables but it doesnt work for me.
$id = $_GET['id];
SELECT ps.id,ps.pdf,ps.emp_id,ps.emp_type,external_employee.name as comemp,
internal_employee.comp_empl_name as comemp
FROM pay_slip as ps
INNER JOIN internal_employee_master as internal_employee ON internal_employee.comp_trad_id = ps.trade_id
INNER JOIN external_employee_master as external_employee ON external_employee.trad_id = ps.trade_id
where ps.is_deleted = 1 AND ps.id = '".$id."'"
Please help me to join query to get name and employee_name with respect to emp_type form pay_slip table.
How about using UNION again?
SELECT
ps.id,
ps.pdf,
ps.emp_id,
ps.emp_type,
external_employee.name AS comemp,
internal_employee.comp_empl_name AS comemp
FROM
pay_slip AS ps
INNER JOIN
internal_employee_master AS internal_employee ON internal_employee.comp_trad_id = ps.trade_id
WHERE
ps.is_deleted = 1 AND ps.id = '".$id."'
AND ps.type = 'internal'
UNION ALL
SELECT
ps.id,
ps.pdf,
ps.emp_id,
ps.emp_type,
external_employee.name AS comemp,
internal_employee.comp_empl_name AS comemp
FROM
pay_slip AS ps
INNER JOIN
external_employee_master AS external_employee ON external_employee.trad_id = ps.trade_id
WHERE
ps.is_deleted = 1 AND ps.id = '".$id."'
AND ps.type = 'external'
You could try this
SELECT ps.id, ps.pay_slip, ps.emp_type, COALESCE(i.employee_name, e.name) AS name
FROM payslips ps
LEFT JOIN internal_employee_master i ON i.id = ps.emp_id AND ps.emp_type = 'internal'
LEFT JOIN external_employee_master e ON e.id = ps.emp_id AND ps.emp_type = 'External'
AND ps.id = :ID
You can see this in action here http://sqlfiddle.com/#!9/53a195/7/0
I would mention that there are a number of issues in your included tables and queries. For example, irregular column names between tables (name vs. employee_name), you've missed the is_deleted column from your example schema, and you have capitalised and non-capitalised values in the emp_type column which is confusing.
I have to build a some complicated mysql query. I have a table with some user informations, with 3 columns: id, id_user, id_campo, valore. So, for example:
1, 1, 1, "Roberto" (where id_campo=1 is for the user name);
2, 2, 1, "Luca";
3, 1, 2, "Windows"; (where id_campo=2 is for used OS);
4, 2, 2, "Linux";
and so on.
Now, I have to select users where: name="Roberto" AND os="Linux", but the same user :
SELECT id_user WHERE (id_campo=1 AND valore="Roberto") OR (id_campo=2 AND valore="Linux").
In this sample case, the query return id_user=1 and id_user=2 but I would obtain no result. How I can modify the query so I can include the condition "the same user" ?
Thanks!
You need to build two "subqueries" and then join them by user id.
SELECT a.id_user
from (
SELECT id_user FROM table
WHERE (id_campo=1 AND valore="Roberto")
) a,
(
SELECT id_user FROM table
WHERE (id_campo=2 AND valore="Linux")
) b
WHERE a.is_user = b.id_user
You have a wrong db design but anyway you can usie an inner join on the same table based on id_user
select a.id_user, a.id_campo, a.valore
from my_table as a
inner join my_table as b on .id_user = b-id_user
where ( a.id_campo = 1 and a.valore ='Roberto')
AND ( b.id_campo = 2 and b.valore ='Linux')
Like below image I have two tables, now I want to get all columns from Restaurant table depending on cat column, and number of records from Foods table that have that Restaurant id.
example : (to get 1,test from Restaurant table and 3 from Foods table).
$sql = "select * from Restaurant,Foods where cat=6..." ;
updated :
$sql = "r.*,(SELECT COUNT(*) FROM restaurant_foods WHERE restaurant_id = r.id)
foods_count FROM restaurant r WHERE r.cats LIKE '%,$cat,%' limit $start,$end"
That should do the job:
SELECT r.*,
(SELECT Count(*)
FROM Foods
WHERE restaurnat_id = r.id) foods_count
FROM Restaurant r
WHERE r.cat = 6
I had the following query (MySQL) that is very slow (about 15 seconds). I have changed the names of columns and tables, so sorry if it has any type error; the original query is working, keep only the concept, no the literal query.
SELECT
id,
b,
(SELECT MAX( day )
FROM all_days
WHERE all_days.id = X.id
) AS day
FROM X
Note that all_days has more than 2 million rows. I have 3 indexes: One for the id, other for the day and other for {id,day}
But if I separate the query in N queries with UNION, it only takes about 1 second or less with the same result:
<?php
$ids = getIds(); // get all ID from X with a query
$i = 0
foreach ($ids as $id) {
if ($i++ > 0) {
$query .= " UNION ";
}
$query .= "SELECT MAX( day )
FROM all_days
WHERE all_days.id = $id";
}
?>
Any ideas of how could I increase the speed without doing UNIONS?
EDIT (added structure):
Table X:
id INTEGER PRIMARY KEY
b INTEGER -- extra info
Table all_days:
day_id INTEGER PRIMARY KEY
id INTEGER FK X.id
day DATETIME
all_days indexes:
id
day
id,day
Please have a try with this query:
SELECT
id,
b,
max_day
FROM X
INNER JOIN
(
SELECT id, MAX(`day`) AS max_day
FROM all_days
GROUP BY id
) AS max_days
ON max_days.id = X.id
The reason why this should be much faster is, that here per id the max(day) is stored in memory (or temporary table on disk if too large) and is then connected to table X. In your query you read every row of table X and for every row you query table all_days.
In a simple situation like this (assuming the combination of X.id / X.b is unique) then this can be done without the need for a sub query:-
SELECT X.id,
X.b,
MAX( all_days.day ) AS day
FROM X
LEFT OUTER JOIN all_days
ON all_days.id = X.id
GROUP BY X.id, X.b
I have a table like following
ID student_name dept email
1 Mary Wise Eng mary-wise#xxx.cc
2 John Walter Sc john-walter#xxx.cc
3 Sophia Jacob Politics sophia-jacob#xxx.cc
4 Ava William Eng ava-william#xxx.cc
5 Mary Wise Politics mary-wise#xxx.cc
6 John Walter Eng john-walter#xxx.cc
7 John Walter Politics john-walter#xxx.cc
8 Sophia Eng sophia#xxx.cc
9 Emma Eng emma#xxx.cc
10 Sherlock Eng sherlock#xxx.cc
The email ids col is generated by firstname-lastname#xxx.cc
The problem is when the name is same the email id is also same.
I want the email id to be appended with 1, 2, 3 when same name exists.
For example in table above
the mary-wise on 5th row should be mary-wise1#xxx.cc,
6th row should be, john-walter1#xxx.cc,
7th row should be, john-walter2#xxx.cc
How can I update my email column with mysql query as fast as possible.
I tried with php with mysql it takes too long when the table contains million rows.
Thanks
I believe it's better for you to make email column unique and to use ON DUPLICATE KEY UPDATE syntax (more here).
You still need to keep track of a number you want to append to the new value. For this purpose you can create a separate table with auto increment field and just get the new value from there.
The following SQL will enumerate the duplicates:
select t.*,
#rn := if(#StudentName = StudentName, 1, #rn + 1) as seqnum,
#StudentName := StudentName
from table t cross join
(select #rn := 0, #StudentName := '') const
order by StudentName;
You can put this in an update using join:
update t join
(select t.*,
#rn := if(#StudentName = StudentName, 1, #rn + 1) as seqnum,
#StudentName := StudentName
from table t cross join
(select #rn := 0, #StudentName := '') const
order by StudentName
) toupdate
on t.name = toupdate.name and toupdate.seqnum > 1
set email = concat(replace(t.StudentName, ' ', '-'), toupdate.seqnum - 1, '#xxx.cc);
It would be easy to achieve if you had CTE (maybe switch to postgres 9 if you can):
SELECT
id
, student_name
, concat(
replace(lower(student_name), ' ', '-')
, case
when cnt > 1 then numb
end
,'#xxx.cc'
) as newmail
FROM (
SELECT
count(*) over (partition BY student_name) as cnt
, count(*) over (partition BY student_name order by id) as numb
, id
, student_name
FROM tab1
order by id
) subq
sqlFiddle demo