Performing JOIN on more than 1 column oracle query - mysql

I have 2 tables, the first one is MASTER_TABLE with fields ID, STATUS_CODE, STATUS_SUBCODE, SUBJECT_CODE, SUBJECT_SUBCODE and the second table is CODE_TABLE which has the unique description for every combination of a code and subcode. It has the following fields CODE, SUBCODE and DESCRIPTION
How to write a query to retrieve the ID, STATUS and SUBJECT , for example for every combination of STATUS_CODE and STATUS_SUBCODE in MASTER_TABLE I have to get the STATUS value in CODE_TABLE, similarly I have to do the same thing for SUBJECT

You must join twice to CODE_TABLE - once for each type of look-up, so to distinguish the rows from eachother, you must alias at least one (but usually one would alias both, as below):
select
mt.ID,
ct1.DESCRIPTION as STATUS
ct2.DESCRIPTION as SUBJECT
from MASTER_TABLE mt
left join CODE_TABLE ct1
on ct1.CODE = mt.STATUS_CODE and ct1.SUBCODE = mt.STATUS_SUBCODE
left join CODE_TABLE ct2
on ct2.CODE = mt.SUBJECT_CODE and ct2.SUBCODE = mt.SUBJECT_SUBCODE
I have made the joins left joins in case data is missing from CODE_TABLE, in which case this query would produce a null for the corresponding description.

Related

mysql left join with group_concat - only shows a single result

So I am not sure if I am taking the right approach but here is what I am after:
I need to get all the records from table A
Then join on table B and concatenate all the values that match a specific ID from Table.
What I am noticing with my query below, is that I only get results where there is a record in Table B - I want to be able to display a NULL value in my result set if there is no corresponding value in Table A
SELECT Account.AccountID, AccountOpenedDate, AccountStatus, GROUP_CONCAT(Expense.ExpenseType SEPARATOR ':') AS Expense FROM Account
JOIN Expense ON Account.AccountID=Expense.AccountID
GROUP BY MONTH(DATE(AccountOpenedDate)), Account.AccountID
ORDER BY Account.AccountID ASC;
I want to return all accounts and account status and opened date
Then if Expense has a value for that row display those values concatenated with ":" as a separator.
I only seem to get results where a record exists in both tables.
You are describing a left join:
select
a.accountID,
a.accountOpenedDate,
a.accountStatus,
group_concat(e.expenseType separator ':') as expense
from account a
left join expense e on e.accountID = a.accountID
group by a.accountID
order by a.accountID
I also don't see the point for expression MONTH(DATE(AccountOpenedDate)) in the GROUP BY clause: you seem to want one row per account, so this seems irrelevant.
The above query works under the assumption that accountID is the primary key of table account: other columns from the same column are functionaly dependent on the primary key, so you do not need to list them in the group by clause. You could also write this as:
select
a.accountID,
a.accountOpenedDate,
a.accountStatus,
group_concat(e.expenseType separator ':') as expense
from account a
left join expense e on e.accountID = a.accountID
group by a.accountID, a.accountOpenedDate, a.accountStatus
order by a.accountID
Side notes:
table aliases make the query easier to write and read
in a multi-table query, all columns should be qualified (prefixed) with the (alias of the) table they belong to

ID missing from one table, include it in the results anyway

In my mySQL database I have two tables called job_details and job_actions. In the job_details table, if I get the Detail_ID for Job_ID 41230, then I get five results. For example:
select Detail_ID from job_details where Job_ID = '41230';
What I want to do is use the same Job_ID to get the Percent_Complete for each Detail_ID from the job_actions table. For example, this yields only 4 records because not all of the Detail_IDs appear in this table:
select Detail_ID, Percent_Complete from job_actions where Job_ID = '41230';
I get the same four records when I try to join both tables:
select
details.Detail_ID,
actions.Percent_Complete
from
job_details details,
job_actions actions
where
details.Job_ID = '41230' and
details.Job_ID = actions.Job_ID and
details.Detail_ID = actions.Detail_ID;
I would like my output to include EVERY Detail_ID found in the job_details table, even if it is not found in the job_actions table. For example:
I know how to find the Detail_ID that is missing from the job_actions table, but not how to include it in the results. For example:
select details.Detail_ID from job_details details
left join job_actions actions using (Detail_ID)
where actions.Detail_ID IS NULL and details.Job_ID = '41230';
How can I include the Detail_ID 87679 in the results even though it is missing from the job_actions table?
Never use commas in the FROM clause. Always use proper, explicit, standard JOIN syntax.
You simply want a LEFT JOIN:
select details.Detail_ID, actions.Percent_Complete
from job_details details left join
job_actions actions
on details.Job_ID = actions.Job_ID and
details.Detail_ID = actions.Detail_ID
where details.Job_ID = 41230; -- I assume Job_ID is a number so the single quotes are not necessary
Since, you have wrote the syntax of joins but with older style with where clause that could turn into actually inner join or equi join.
So, use proper explicit join syntax with type of left join
select jd.Detail_ID, ja.Percent_Complete
from job_details jd left join job_actions ja on
ja.Job_ID = jd.Job_ID and
ja.Detail_ID = jd.Detail_ID
where jd.Job_ID = '41230';
You could also use subquery instead since you are looking for all Detail_ID from job_details table
select Detail_ID,
(select Percent_Complete from job_actions
where Job_ID = jd.Job_ID and
Detail_ID = jd.Detail_ID) as Percent_Complete -- Use limit with order by clause in case one or more Percent found.
from job_details jd
where Job_ID = '41230';
I suspect, if you have Job_ID as type of numeric then you don't need to use of quotes just use value (i.e. 41230)

Create view from two tables with subtract operation

I'm almost new with SQL syntax and I need help to create a view on MySQL.
I have a table with a PK column called ID, a column called total_seats and another one is title.
In the second table, I have multiple rows, with a firstname column and a FK that corresponds to the PK (total_seats) present in the first table.
I need to create a view where I can calculate the available_seats (total_seats minus occurrence in the second table) for each element present in the first table.
Actually I'm calculating the "occupied" seats but the join give me the result only for already taken event, so the result is that I don't see the available_seats for the empty event.
SELECT b.ID_event, a.*,
COUNT(*) AS occupied FROM second_table b
LEFT JOIN first_table a ON b.ID_event = a.ID
GROUP BY ID_event
You could subtract the count
select a.ID_event, a.total_seats, count(*) as occupied, a.total_seats - count(*) difference
from first_table a
left join second_table ba ON b.ID_event = a.ID
group by a.ID_event, a.total_seats

Sql query returns row which was not specified by Where clause

My SQL query doesn't return an output that suppose to be specified by my where clause.
Here is my query:
SELECT
transaction_details.transaction_id
,transaction_details.transaction_number
,transaction_details.product_id
,Products3.ProductName
FROM transaction_details
INNER JOIN Products3
ON transaction_details.product_id = Products3.productID
INNER JOIN transaction_status
ON transaction_details.transaction_id = transaction_status.transaction_id
WHERE status_of_transaction = 'review'
This query should return me table rows with a status_of_transaction = 'review'.
Here is my table which contains the status_of_transaction
I tried DISTINCT but its not working.
and this is the output I always get:
is there something wrong with my query its is returning table row which was not specified by my WHERE clause?
There are multiple rows generated by the set (remember this is all set theory) - you are missing a Foreign Key/Primary Key (FK/PK) relationship in the JOIN. I'll bet you missed a column in the INNER JOIN "ON" statement. There are probably two columns necessary to JOIN on to find the proper solution.
I suggest either picking it apart table by table, or using select * and look for the difference in the column values between each row. One column should be different - which you currently cannot see (i.e. hidden) because the column is not in the current SELECT statement.
Try this...
SELECT
transaction_status.*
FROM transaction_details
INNER JOIN Products3
ON transaction_details.product_id = Products3.productID
INNER JOIN transaction_status
ON transaction_details.transaction_id = transaction_status.transaction_id
WHERE status_of_transaction = 'review'
I believe the issue is with the transaction_status join. The transaction_id is the same for both rows in transaction_details - which matches TWO rows in transaction_status. SQL will create 4 rows -- two rows that match "review" and two rows for "replied" (remove the WHERE to see them). This is a cross join of sorts.
Does the _status table also contain transaction_number? There needs to be a way to JOIN to the single row in transaction_details to a single row in transaction_status. Somehow that _status row belongs to the _details row. Look at (or ask the DBA) the PK/FK definitions for both tables.
Not knowing your schema - I would guess the solution is....
SELECT
transaction_details.transaction_id
,transaction_details.transaction_number
,transaction_details.product_id
,Products3.ProductName
FROM transaction_details
INNER JOIN Products3
ON transaction_details.product_id = Products3.productID
INNER JOIN transaction_status
ON transaction_details.transaction_id = transaction_status.transaction_id
-- ADDED NEXT LINE
AND transaction_details.transaction_number = transaction_status.transaction_number
-- END Change
WHERE status_of_transaction = 'review'
Most likely one of the inner joins is matching more than one row, so it generates two rows in the output set. Run the query with:
select transaction_details.transaction_id
, Products3.product_id
, transaction_details.detail_id
to examine which join is the culprit.

How can I select data from one table depending on the data from another table

I have 2 tables: contracts_main_list and contracts_detail.
In contracts_main_list I have columns:
user_id
contract_id
and in contracts_detail:
contract_id
other columns with data
I need to select all the rows from the table contracts_main_list WHERE user_id = some number.
From these rows I need to get the list of contract numbers (from column contract_id) and according to them select rows corresponding to each of the contract number from the list. So something like:
WHERE contracts_detail.contract_id = contracts_main_list.contract_id
The contract_ids are probably gonna be unique, but in case there is some kind of error and there will be more rows with the same contract_id in either of the tables, I need to select only one row (so probably using DISTINCT) and select the latest record (both tables have a column id as a primary key)
Also if there is no row in contracts_detail matching with the contract_id to the contract_id of the first table contracts_main_list it should skip the row. But I guess the condition:
WHERE contracts_detail.contract_id = contracts_main_list.contract_id
already covers it.
I hope I made it clear enough. What I am trying to do in real life is show list of contracts with all the relevant data belonging to the user.
To sum this up, I need to find all the contracts belonging to the user and select the rows with details about each contract and finally get the data from the contracts_detail table as a result.
Here is the result you're looking for:
SELECT CD.*
FROM (SELECT C2.contract_id
,MAX(C2.id) AS last_main_list_id
,MAX(CD2.id) AS last_contracts_detail_id
FROM contracts_main_list C2
INNER JOIN contracts_detail CD2 ON CD2.contract_id = C2.contract_id
GROUP BY C2.contract_id) L
INNER JOIN contracts_main_list C ON C.id = L.last_main_list_id
AND C.user_id = ?
INNER JOIN contracts_detail CD ON CD.id= L.last_contracts_detail_id
This query use a subquery for the FROM because of the following indication you provided:
The contract_ids are probably gonna be unique, but in case there is
some kind of error and there will be more rows with the same
contract_id in either of the tables, I need to select only one row
If you're sure that the contract_id are unique, here is the same query without this check on contract_id:
SELECT CD.*
FROM contracts_main_list C
INNER JOIN contracts_detail CD ON CD.contract_id = C.contract_id
WHERE C.user_id = ?
Hope this will help you.