I want to join multiple tables with SQL.
Here is my table structure:
table 1: akdhis_mahasiswamagister (ID, MahasiswaID, NIM, MayorID, TahunMasuk)
table 2: akdmst_mayor(ID, DepartemenID)
table 3: ipbmst_departemen(ID, FakultasID, DepartmenName)
table 4: ipbmst_fakultas(ID, FacultyName)
table 5: ipbmst_orang(ID, Name, NIMS2Key)
table 6: akdhis_kelanjutanstudi(ID, NIM, IPK)
I want to create "a view table" by joining with this query:
CREATE ALGORITHM=UNDEFINED DEFINER=`root`#`localhost` SQL SECURITY DEFINER VIEW `aIPK` AS select
`ipbmst_fakultas`.`Kode` AS `Fakultas`,
`ipbmst_departemen`.`Kode` AS `Departemen`,
`akdmst_mahasiswamagister`.`NIM` AS `NIM`,
`akdmst_mahasiswamagister`.`TahunMasuk` AS `TahunMasuk`,
`akdhis_kelanjutanstudi`.`IPK` AS `IPK`
from (((((`akdmst_mahasiswamagister` left join `akdmst_mayor` on((`akdmst_mahasiswamagister`.`MayorID` = `akdmst_mayor`.`ID`)))
left join `ipbmst_departemen` on((`akdmst_mayor`.`DepartemenID` = `ipbmst_departemen`.`ID`)))
left join `ipbmst_fakultas` on((`ipbmst_departemen`.`FakultasID` = `ipbmst_fakultas`.`ID`)))
left join `ipbmst_orang` on((`akdmst_mahasiswamagister`.`NIM` = `ipbmst_orang`.`NIMS2Key`)))
left join `akdhis_kelanjutanstudi` on((`akdhis_kelanjutanstudi`.`NIM` = `ipbmst_orang`.`NIMS2Key`)))
WHERE IPK IS NOT NULL
order by NIM
LIMIT 100;
but, when I tried to run it, the result is empty result. What should I do to solve that problem? Thankyou
I want to create a view which combines the data with the maximal date from the tables shown in the picture. These should be grouped by the profileID.
Database ERM
The profileIDs are linked to profile.userID.
I tried different approches in my code. The fort one slects the data where date is max, but the join doesn't work. Every profileID will be joined with the same data.
CREATE
ALGORITHM = UNDEFINED
DEFINER = `b91788dd8d05b5`#`%`
SQL SECURITY DEFINER
VIEW fitchallengersql1.profileview AS
Select p.userID,
(SELECT
`bf`.`bodyFat`
FROM
(`fitchallengersql1`.`bodyfatprofile` `bf`
JOIN `fitchallengersql1`.`profile` `p`)
WHERE
((`bf`.`profileID` = `p`.`userID`)
AND (`bf`.`date` = (SELECT
MAX(`fitchallengersql1`.`bodyfatprofile`.`date`)
FROM
`fitchallengersql1`.`bodyfatprofile`)))) AS `bodyFat`,
(SELECT
`bw`.`bodyweight`
FROM
(`fitchallengersql1`.`bodyweightprofile` `bw`
JOIN `fitchallengersql1`.`profile` `p`)
WHERE
((`bw`.`profileID` = `p`.`userID`)
AND (`bw`.`date` = (SELECT
MAX(`fitchallengersql1`.`bodyweightprofile`.`date`)
FROM
`fitchallengersql1`.`bodyweightprofile`)))) AS `bodyWeight`,
(SELECT
`bmi`.`bmi`
FROM
(`fitchallengersql1`.`bmiprofile` `bmi`
JOIN `fitchallengersql1`.`profile` `p`)
WHERE
((`bmi`.`profileID` = `p`.`userID`)
AND (`bmi`.`date` = (SELECT
MAX(`fitchallengersql1`.`bmiprofile`.`date`)
FROM
`fitchallengersql1`.`bmiprofile`)))) AS `bmi`
From profile
In the second one the join works how it should, but I can't figure out a way to select just the data where date is max.
CREATE
ALGORITHM = UNDEFINED
DEFINER = `b91788dd8d05b5`#`%`
SQL SECURITY DEFINER
VIEW `fitchallengersql1`.`profileview` AS
SELECT
`p`.`userID` AS `userID`,
`p`.`privacy` AS `privacy`,
`bs`.`size` AS `bodysize`,
`bw`.`bodyweight` AS `bodyweight`,
`bf`.`bodyFat` AS `bodyfat`,
`bmi`.`bmi` AS `bmi`
FROM
((((`fitchallengersql1`.`profile` `p`
JOIN `fitchallengersql1`.`bodysizeprofile` `bs`)
JOIN `fitchallengersql1`.`bodyweightprofile` `bw`)
JOIN `fitchallengersql1`.`bmiprofile` `bmi`)
JOIN `fitchallengersql1`.`bodyfatprofile` `bf`)
WHERE
((`p`.`userID` = `bs`.`profileID`)
AND (`p`.`userID` = `bw`.`profileID`)
AND (`p`.`userID` = `bmi`.`profileID`)
AND (`p`.`userID` = `bf`.`profileID`))
Hope someone could help me.
Thank you!
fleewe
Hope following query gives what you need. Please follow the pattern and join the rest of the tables. Please note that when the table grows these will definitely have performance issues as this require huge processing.
-- Select the columns that you need
select p.*, lbp.*
from profile p
inner join (
-- get the latest bmiprofile per user profile
select bp1.*
from bmiprofile bp1
inner join (select profileID, max(date) as date from bmiprofile group by profileID) as bp2 on bp1.prfileId = bp2.profileId and bp1.date = bp2.date
) as lbp on lbp.ProfileId = p.userId
-- Join the other tables in similar way
this is only a comment, but I needed formating capability:
Don't place the joining predicates into the where clause if using ANSI join syntax, instead use ON followed by the relevant predicates. e.g.
FROM `fitchallengersql1`.`profile` `p`
JOIN `fitchallengersql1`.`bodysizeprofile` `bs` ON `p`.`userID` = `bs`.`profileID`
JOIN `fitchallengersql1`.`bodyweightprofile` `bw` ON `p`.`userID` = `bw`.`profileID`
JOIN `fitchallengersql1`.`bmiprofile` `bmi` ON `p`.`userID` = `bmi`.`profileID`
JOIN `fitchallengersql1`.`bodyfatprofile` `bf` ON `p`.`userID` = `bf`.`profileID`
how to write following SQL using jOOQ?
SELECT *
FROM food_db_schema.tblCategory AS t1
LEFT OUTER JOIN food_db_schema.tblCategory AS t2 ON t1.category_id = t2.parent_id
WHERE t2.parent_id IS NULL
AND t1.heartbeat = "ALIVE";
database is mySQL
flesk's answer depicts nicely how this can be done with jOOQ 1.x. A self-join using aliasing is more or less equivalent to a regular join using aliasing as described in the manual:
https://www.jooq.org/doc/latest/manual/sql-building/table-expressions/aliased-tables/
In the upcoming version 2.0, aliasing will be made less verbose and more type-safe. Hence flesk's solution could be simplified as such:
// Type-safe table aliasing:
TblCategory t1 = TBLCATEGORY.as("t1");
TblCategory t2 = TBLCATEGORY.as("t2");
Record record = create.select()
.from(t1)
// t1 and t2 give access to aliased fields:
.leftOuterJoin(t2).on(t1.CATEGORY_ID.equal(t2.PARENT_ID))
.where(t2.PARENT_ID.isNull())
.and(t1.HEARTBEAT.equal("ALIVE"));
I have also described a more complex example for a self-join here:
http://blog.jooq.org/jooq-meta-a-hard-core-sql-proof-of-concept/
Maybe
SELECT *
FROM food_db_schema.tblCategory AS t1
WHERE t1.category_id IS NULL
AND t1.heartbeat = "ALIVE";
, but are you sure t2.parent_id is both supposed to be NULL and equal to t1.category_id?
EDIT:
Then something like
Table<TblCategoryRecord> t1 = TBLCATEGORY.as("t1");
Table<TblCategoryRecord> t2 = TBLCATEGORY.as("t2");
Field<Integer> t1CategoryId = t1.getField(TblCategory.CATEGORY_ID);
Field<String> t1Heartbeat = t1.getField(TblCategory.HEARTBEAT);
Field<Integer> t2ParentId = t2.getField(TblCategory.PARENT_ID);
Record record = create.select().from(t1)
.leftOuterJoin(t2).on(t1CategoryId.equal(t2ParentId))
.where(t2ParentId.isNull())
.and(t1Heartbeat.equal("ALIVE"));
depending on what the generated classes, properties and meta-model objects are called.
I am creating a view for my Database , I am joing 3 tables, Users,personal_info and contact_info, if you notice I have a lot of column names in my Select statement , since i don't want to include primary keys but it seems I have an error here, take a look
CREATE VIEW `payroll`.`new_view` AS
Select employee_id,employee_password,First_Name,Middle_Initial,
Last_Name,Date_Of_Birth,Beneficiaries,Home_Number,Address,Mobile_Number,Email_Address
From USER
LEFT JOIN personal_info on idUser = idPersonal_Info,
FULL JOIN contact_info on idUser = idContact_Info
The error is
ERROR 1146: Table 'payroll.full' doesn't exist
SQL Statement:
CREATE OR REPLACE VIEW `payroll`.`new_view` AS
Select employee_id,employee_password,First_Name,Middle_Initial,
Last_Name,Date_Of_Birth,Beneficiaries,Home_Number,Address,Mobile_Number,Email_Address
From USER
LEFT JOIN personal_info on idUser = idPersonal_Info,
FULL JOIN contact_info on idUser = idContact_Info
quote it with backtics: payroll.new_view
CREATE VIEW `payroll.new_view`
Error on:
LEFT JOIN personal_info on idUser = idPersonal_Info
you need to specify which column on which table equals which one on the other table, like
SELECT a,b,c from table1
LEFT JOIN table2
on table1.a= table2.columnY
in your case:
on USER.idUser = Personal_Info.idPersonalInfo
and the same for the 3rd Join
Another thing is the Comma at the end of the line:
LEFT JOIN personal_info on idUser = idPersonal_Info ,
it doesnt belong there.
I need to check (from the same table) if there is an association between two events based on date-time.
One set of data will contain the ending date-time of certain events and the other set of data will contain the starting date-time for other events.
If the first event completes before the second event then I would like to link them up.
What I have so far is:
SELECT name as name_A, date-time as end_DTS, id as id_A
FROM tableA WHERE criteria = 1
SELECT name as name_B, date-time as start_DTS, id as id_B
FROM tableA WHERE criteria = 2
Then I join them:
SELECT name_A, name_B, id_A, id_B,
if(start_DTS > end_DTS,'VALID','') as validation_check
FROM tableA
LEFT JOIN tableB ON name_A = name_B
Can I then, based on my validation_check field, run a UPDATE query with the SELECT nested?
You can actually do this one of two ways:
MySQL update join syntax:
UPDATE tableA a
INNER JOIN tableB b ON a.name_a = b.name_b
SET validation_check = if(start_dts > end_dts, 'VALID', '')
-- where clause can go here
ANSI SQL syntax:
UPDATE tableA SET validation_check =
(SELECT if(start_DTS > end_DTS, 'VALID', '') AS validation_check
FROM tableA
INNER JOIN tableB ON name_A = name_B
WHERE id_A = tableA.id_A)
Pick whichever one seems most natural to you.
UPDATE
`table1` AS `dest`,
(
SELECT
*
FROM
`table2`
WHERE
`id` = x
) AS `src`
SET
`dest`.`col1` = `src`.`col1`
WHERE
`dest`.`id` = x
;
Hope this works for you.
Easy in MySQL:
UPDATE users AS U1, users AS U2
SET U1.name_one = U2.name_colX
WHERE U2.user_id = U1.user_id
If somebody is seeking to update data from one database to another no matter which table they are targeting, there must be some criteria to do it.
This one is better and clean for all levels:
UPDATE dbname1.content targetTable
LEFT JOIN dbname2.someothertable sourceTable ON
targetTable.compare_field= sourceTable.compare_field
SET
targetTable.col1 = sourceTable.cola,
targetTable.col2 = sourceTable.colb,
targetTable.col3 = sourceTable.colc,
targetTable.col4 = sourceTable.cold
Traaa! It works great!
With the above understanding, you can modify the set fields and "on" criteria to do your work. You can also perform the checks, then pull the data into the temp table(s) and then run the update using the above syntax replacing your table and column names.
Hope it works, if not let me know. I will write an exact query for you.
UPDATE
receipt_invoices dest,
(
SELECT
`receipt_id`,
CAST((net * 100) / 112 AS DECIMAL (11, 2)) witoutvat
FROM
receipt
WHERE CAST((net * 100) / 112 AS DECIMAL (11, 2)) != total
AND vat_percentage = 12
) src
SET
dest.price = src.witoutvat,
dest.amount = src.witoutvat
WHERE col_tobefixed = 1
AND dest.`receipt_id` = src.receipt_id ;
Hope this will help you in a case where you have to match and update between two tables.
I found this question in looking for my own solution to a very complex join. This is an alternative solution, to a more complex version of the problem, which I thought might be useful.
I needed to populate the product_id field in the activities table, where activities are numbered in a unit, and units are numbered in a level (identified using a string ??N), such that one can identify activities using an SKU ie L1U1A1. Those SKUs are then stored in a different table.
I identified the following to get a list of activity_id vs product_id:-
SELECT a.activity_id, w.product_id
FROM activities a
JOIN units USING(unit_id)
JOIN product_types USING(product_type_id)
JOIN web_products w
ON sku=CONCAT('L',SUBSTR(product_type_code,3), 'U',unit_index, 'A',activity_index)
I found that that was too complex to incorporate into a SELECT within mysql, so I created a temporary table, and joined that with the update statement:-
CREATE TEMPORARY TABLE activity_product_ids AS (<the above select statement>);
UPDATE activities a
JOIN activity_product_ids b
ON a.activity_id=b.activity_id
SET a.product_id=b.product_id;
I hope someone finds this useful
UPDATE [table_name] AS T1,
(SELECT [column_name]
FROM [table_name]
WHERE [column_name] = [value]) AS T2
SET T1.[column_name]=T2.[column_name] + 1
WHERE T1.[column_name] = [value];
You can update values from another table using inner join like this
UPDATE [table1_name] AS t1 INNER JOIN [table2_name] AS t2 ON t1.column1_name] = t2.[column1_name] SET t1.[column2_name] = t2.column2_name];
Follow here to know how to use this query http://www.voidtricks.com/mysql-inner-join-update/
or you can use select as subquery to do this
UPDATE [table_name] SET [column_name] = (SELECT [column_name] FROM [table_name] WHERE [column_name] = [value]) WHERE [column_name] = [value];
query explained in details here http://www.voidtricks.com/mysql-update-from-select/
You can use:
UPDATE Station AS st1, StationOld AS st2
SET st1.already_used = 1
WHERE st1.code = st2.code
For same table,
UPDATE PHA_BILL_SEGMENT AS PHA,
(SELECT BILL_ID, COUNT(REGISTRATION_NUMBER) AS REG
FROM PHA_BILL_SEGMENT
GROUP BY REGISTRATION_NUMBER, BILL_DATE, BILL_AMOUNT
HAVING REG > 1) T
SET PHA.BILL_DATE = PHA.BILL_DATE + 2
WHERE PHA.BILL_ID = T.BILL_ID;
I had an issue with duplicate entries in one table itself. Below is the approaches were working for me. It has also been advocated by #sibaz.
Finally I solved it using the below queries:
The select query is saved in a temp table
IF OBJECT_ID(N'tempdb..#New_format_donor_temp', N'U') IS NOT NULL
DROP TABLE #New_format_donor_temp;
select *
into #New_format_donor_temp
from DONOR_EMPLOYMENTS
where DONOR_ID IN (
1, 2
)
-- Test New_format_donor_temp
-- SELECT *
-- FROM #New_format_donor_temp;
The temp table is joined in the update query.
UPDATE de
SET STATUS_CD=de_new.STATUS_CD, STATUS_REASON_CD=de_new.STATUS_REASON_CD, TYPE_CD=de_new.TYPE_CD
FROM DONOR_EMPLOYMENTS AS de
INNER JOIN #New_format_donor_temp AS de_new ON de_new.EMP_NO = de.EMP_NO
WHERE
de.DONOR_ID IN (
3, 4
)
I not very experienced with SQL please advise any better approach you know.
Above queries are for MySql server.
if you are updating from a complex query. The best thing is create temporary table from the query, then use the temporary table to update as one query.
DROP TABLE IF EXISTS cash_sales_sums;
CREATE TEMPORARY TABLE cash_sales_sums as
SELECT tbl_cash_sales_documents.batch_key, COUNT(DISTINCT tbl_cash_sales_documents.cash_sale_number) no_of_docs,
SUM(tbl_cash_sales_documents.paid_amount) paid_amount, SUM(A.amount - tbl_cash_sales_documents.bonus_amount - tbl_cash_sales_documents.discount_given) amount,
SUM(A.recs) no_of_entries FROM
tbl_cash_sales_documents
RIGHT JOIN(
SELECT
SUM(
tbl_cash_sales_transactions.amount
)amount,
tbl_cash_sales_transactions.cash_sale_document_id,
COUNT(transaction_id)recs
FROM
tbl_cash_sales_transactions
GROUP BY
tbl_cash_sales_transactions.cash_sale_document_id
)A ON A.cash_sale_document_id = tbl_cash_sales_documents.cash_sale_id
GROUP BY
tbl_cash_sales_documents.batch_key
ORDER BY batch_key;
UPDATE tbl_cash_sales_batches SET control_totals = (SELECT amount FROM cash_sales_sums WHERE cash_sales_sums.batch_key = tbl_cash_sales_batches.batch_key LIMIT 1),
expected_number_of_documents = (SELECT no_of_docs FROM cash_sales_sums WHERE cash_sales_sums.batch_key = tbl_cash_sales_batches.batch_key),
computer_number_of_documents = expected_number_of_documents, computer_total_amount = control_totals
WHERE batch_key IN (SELECT batch_key FROM cash_sales_sums);
INSERT INTO all_table
SELECT Orders.OrderID,
Orders.CustomerID,
Orders.Amount,
Orders.ProductID,
Orders.Date,
Customer.CustomerName,
Customer.Address
FROM Orders
JOIN Customer ON Orders.CustomerID=Customer.CustomerID
WHERE Orders.OrderID not in (SELECT OrderID FROM all_table)