Join on multiple tables - mysql

I have 2 SQL tables:
select * from operation;
id | name
----+--------------------
1 | Account add
2 | Account edit
select * from role_operation;
id | role | operation
----+----------+-----------
1 | admin | 1
2 | operator | 1
3 | admin | 2
The id column in operation table and the operation column in role_operation are linked. (Foreign key). How can I get all rows where operation name = Account add
I tried SELECT role_operation.role, operation.name FROM role_operation INNER JOIN operation ON role_operation.operation=operation.id;
But this gives me all the rows which have an operation id present in the operation field of role_operation table.

use where
SELECT role_operation.role, operation.name
FROM role_operation
INNER JOIN operation ON role_operation.operation=operation.id
where operation.name = 'Account add';

SELECT role_operation.role, operation.name FROM role_operation
INNER JOIN operation on operation.id = role_operation.operation
WHERE operation.name='Account add'

Related

Exclude based on sub-table's value

Consider the table Audit, and AuditStatus.
Where auditId in AuditStatus is a foreign key, mapping the pk of table Audit.
table Audit
id | auditName |
1 | test |
2 | fooTest |
3 | barTest |
table AuditStatus
id | auditId | status |
11 | 1 | started |
12 | 1 | completed |
13 | 2 | started |
How can I only select the entries of table Audit, which do not have a AuditStatus.status 'completed'.
The result in this case would be:
2 | fooTest |
3 | barTest |
I have updated the question and the result example, to make it more clear. The relation Audit -> AuditStatus is a one to many. And I want to exclude the Audits which have a refrerence to an AuditStatus with status 'complete'
You should post your attempted query into your question, not as comment. Anyway, your query is actually correct but your condition is incorrect. Let's inspect your query:
SELECT *
FROM Audit a
WHERE NOT EXISTS (
SELECT s.auditId
FROM AuditStatus s
WHERE a.id = s.auditId AND s.status != 'completed'
);
You're suppose to find where the status is not complete, which is true in the subquery but the problem here is you're doing a NOT EXISTS which negates the correct result you're getting from the subquery.
This is what your subquery will return:
id
auditId
status
11
1
started
13
2
started
Then when your NOT EXIST negates the auditId being returned, you'll get this result instead:
id
auditName
3
barTest
Which is correct according to the condition; auditId=3 wasn't returned in the subquery. What you need to modify is actually very simple, you just need to make the subquery return status = completed as true then NOT EXISTS will return any Audit.Id that doesn't match with the correlated subquery. Therefore:
SELECT *
FROM Audit a
WHERE NOT EXISTS (
SELECT s.auditId
FROM AuditStatus s
WHERE a.id = s.auditId AND s.status = 'completed'
);
And that's it, you should be getting the result you looking for.
Demo fiddle
maybe use a left join like below which only joins on Audit Status on Fk as well as status constraint
SELECT *
FROM Audit A
LEFT JOIN AuditStatus ATS
ON A.id= ATS.auditId AND ATS.Status ='completed'
WHERE AS.auditId IS NULL

How to find all the opposite combinations between two columns in SQL

I am making a web dating app that needs to match users and let them chat with each other.
I want to figure out how to find all the matches for a particular user.
Right now I have a table called follows that has 2 columns.
UserID | MatchUserID
--------------------
1 | 2
2 | 1
1 | 3
1 | 4
1 | 5
4 | 1
5 | 4
The idea is that for two users to match they need to follow one another. The table above shows which user follows which.
Assuming that the user who is currently logged on is UserID = 1.
I need a query that will return from the MatchUserID table the following results:
2, 4
In a way, I am looking to find all the opposite combinations between the two columns.
This is the code I use to create the table.
CREATE TABLE Match
(
UserID INT NOT NULL,
MatchUserID INT NOT NULL,
PRIMARY KEY (UserID, MatchUserID)
);
You can do it with a self join:
select m.MatchUserID
from `Match` m inner join `Match` mm
on mm.MatchUserID = m.UserId
where
m.UserId = 1
and
m.MatchUserID = mm.UserId
See the demo.
Results:
| MatchUserID |
| ----------- |
| 2 |
| 4 |
The simplest way possibly is to use EXISTS and a correlated subquery that searches for the other match.
SELECT t1.matchuserid
FROM elbat t1
WHERE t1.userid = 1
AND EXISTS (SELECT *
FROM elbat t2
WHERE t2.matchuserid = t1.userid
AND t2.userid = t1.matchuserid);

SQL Union SELECT from two tables then combine to one row

I have two tables (tests and reserved) which reference each other it is a 1:1 relationship.
One test's ID is reserved for another test's ID which is in the same table but kept in the reserved table as a look up.
Here's some sample data:
tests:
test_id | summary_id | ref
1 | 1 | ref1
2 | 2 | ref2
reserved:
reserved_id | reserved_summary_id | reserved_for_summary_id
1 | 1 | 2
Currently I am using a UNION to get them both:
SELECT * FROM reserved r, tests t WHERE t.summary_id = r.reserved_summary_id
UNION
SELECT * FROM reserved r, tests t WHERE t.summary_id = r.reserved_for_summary_id
I have a fiddle here.
How can I combine that query into one row? I have tried this one from SO. But get an error.
Are you trying to JOIN the summary table twice with the the tests table so you can access the details of each reserved_summary and reserved_for_summary ?
If yes, then you need :
SELECT
r.reserved_id,
t1.ref ref_of_reserved_summary_id,
t2.ref ref_of_reserved_for_summary_id
FROM
reserved r
INNER JOIN tests t1 ON t1.summary_id = r.reserved_summary_id
INNER JOIN tests t2 ON t2.summary_id = r.reserved_for_summary_id
This will return something like :
reserved_id | ref_of_reserved_summary_id | ref_of_reserved_for_summary_id
1 | ref1 | ref2
You can switch to LEFT JOIN to avoid filtering out records where one of the summaries is not registered in the tests table.

SUM() over a many-to-many relation in MYSQL

I have tables stanje and transakcija in a many-to-many relation, as shown in the image:
I need a MYSQL clause that returns all rows in stanje joined by a SUM() of every transakcija.iznos connected to a given stanje .
So far I have tried
select SUM(t.iznos)
from transakcija t
where transakcija_id in
(select transakcija_id from stanje_transakcija where stanje_id = ?)
which returns the SUM() correctly when given a stanje_id, but have no idea how to proceed, since I need sums for all rows in stanje.
Edit: added example output
------------------------------------
| stanje_id | naziv | SUM(t.iznos) |
------------------------------------
| 1 | a | 125.2 |
| 2 | b | -42.2 |
------------------------------------
If I understand correctly, you need to use JOIN in thoes tables by transakcija_id column and stanje_id column.
From your expect result you can try to use SUM with GROUP BY
select t2.stanje_id,t2.naziv,SUM(t.iznos)
from transakcija t
INNER JOIN stanje_transakcija t1 on t.transakcija_id = t1.transakcija_id
INNER JOIN stanje t2 on t2.stanje_id = t1.stanje_id
GROUP BY t2.stanje_id,t2.naziv

mysql Select Query based on same table

i have a mysql table promotions main fields are
PromotionMaintenanceID (Primary)
PID
PromotionID
PromotionName
I have a special case where the PromotionID of one record (This will be the main Record) become the PID of some of some other records. I need to create a MySql statement to get record with PromotionMaintenanceID (of main Record) , PromotionID (of main Record) , PromotionName (of main Record) and PromotionID of all the records which has PID =PromotionID of the main record
PromotionMaintenanceID ,PID , PromotionID ,PromotionName
1 | T1 | 12 | Promo1
2 | 12 | 22 | PromoSub
3 | 12 | 33 | PromoSub2
I need my result like
PromotionMaintenanceID | PID | PromotionID | PromotionName | Sub PromoID
1 | T1 | 12 | Promo1 |22,33
Any one know how the query should be?
This query (SQLFiddle) should do what you want:
SELECT p1.PromotionMaintenanceID, p1.PID, p1.PromotionID, p1.PromotionName, GROUP_CONCAT(p2.PromotionID) AS `Sub PromoID`
FROM promotions p1
JOIN promotions p2
ON p2.PID = p1.PromotionID
GROUP BY p1.PromotionID
Output:
PromotionMaintenanceID PID PromotionID PromotionName Sub PromoID
1 T1 12 Promo1 33,22
For that you should be able to do a straight join (or double select depending on your favourite way)
SELECT
a.PromotionID,
a.MaintenanceId,
a.PromotionName,
GROUP_CONCAT(b.PID) as SubIds
FROM
PromotionTable a
LEFT JOIN
PromotionTable b
ON
a.PromotionID = b.PID
//ADD AND's here with a.(column) = b.PID if you absolutely need all the ID's for each column to link up
GROUP BY
a.PromotionID, a.MaintenanceID, a.PromotionName