Simple query issue with multiple tables and mismatching IDs - mysql

I'm having trouble with a simple MySQL Query.
Here is the query:
SELECT distinct e.E_CODE, s.S_CODE, p.P_ID, p.P_NAME, p.P_FIRSTNAME, p.P_STATUS, e.E_BOSS, tp.TP_TITLE
from event_participation ep, worker p, type_participation tp, event e, section s
where ep.P_ID = p.P_ID
and s.S_ID = e.S_ID
and ep.TP_ID = tp.TP_ID
and e.E_CODE = ep.E_CODE
The problem is that ep.TP_ID sometimes has a value set to zero while tp.TP_ID has nothing with a zero ID. It's auto-increment and starts at 1 and so on.
The result is obviously that this query does not return records when the ep.TP_ID = 0 and there is no match in tp.TP_ID.
So I'm trying to figure out a way to get those results in there anyway. I was thinking of using a LEFT JOIN statement but couldn't figure out a proper way to insert it into the query.
Any advice on this matter would be greatly appreciated.

First of all, I advice you to use some general type for event_participation records without type; But, unless to take that decision, supposing you want to get all matching records between all tables but also get results with no type, you can use the following query:
SELECT DISTINCT e.E_CODE, s.S_CODE, p.P_ID, p.P_NAME, p.P_FIRSTNAME, p.P_STATUS, e.E_BOSS, tp.TP_TITLE
FROM event_participation ep
JOIN worker p ON (ep.P_ID = p.P_ID)
JOIN event e ON (e.E_CODE = ep.E_CODE)
JOIN section s ON (s.S_ID = e.S_ID)
LEFT JOIN type_participation tp ON (ep.TP_ID = tp.TP_ID)

SELECT DISTINCT e.E_CODE
, s.S_CODE
, p.P_ID
, p.P_NAME
, p.P_FIRSTNAME
, p.P_STATUS
, e.E_BOSS
, tp.TP_TITLE
FROM event_participation ep
JOIN worker p
ON p.P_ID = ep.P_ID
JOIN event e
ON e.E_CODE = ep.E_CODE
JOIN section s
ON s.S_ID = e.S_ID
LEFT
JOIN type_participation tp
ON tp.TP_ID = ep.TP_ID;

Related

How do I make this complex query run faster?

This query is taking between 20-40 seconds to run. I need to speed it up greatly if possible.
SELECT DISTINCT a.category, a.key
FROM system_permissions AS a, system_permission_to_role AS b,
system_user_to_role AS c, system_users AS d
WHERE
(
(
a.system_permission_id=b.system_permission_id
AND (b.system_role_id=c.system_role_id || c.system_role_id = 0)
AND a.system_permission_id NOT IN (
SELECT system_permission_id FROM system_permission_exclusions AS f
WHERE d.system_user_id=f.system_user_id
)
AND c.system_user_id=d.system_user_id
)
OR a.system_permission_id IN (
SELECT system_permission_id
FROM system_permission_inclusions AS g
WHERE d.system_user_id=g.system_user_id
)
)
AND d.ldap_objectguid = '?';
The reason behind doing it this way is that I am creating exclusion and inclusion tables for permissions that fall outside of the standard defined roles, so first I need to exclude ones that are part of the role but exist in the exclusion table, then I need to add ones that are NOT part of their role, but exist in the inclusion table.
I am open to the idea of redesigning the tables also.
Does this work?
SELECT DISTINCT P.category, P.key
FROM system_users U
LEFT OUTER JOIN system_permission_inclusions PI ON PI.system_user_id = U.system_user_id
INNER JOIN system_user_to_role UR ON UR.system_user_id = U.system_user_id
INNER JOIN system_permission_to_role PR ON PR.system_role_id = UR.system_role_id
INNER JOIN system_permissions P ON P.system_permission_id = PR.system_permission_id OR P.system_permission_id = PI.system_permission_id
WHERE U.ldap_objectguid = '?'
AND P.system_permission_id NOT IN (SELECT system_permission_id FROM system_permission_exclusions WHERE system_user_id = U.system_user_id)

Full outer join in mysql with movie database

Hi I have the following tables and columns.
movie: ID, title
person: ID, name
involved: personID, movieID
I need to answer the question:
"Which movies have either John Travolta or Uma Thurman, but not both starred in?"
I couldn't figure out how to do this without creating new tables, so I made 2 new tables. And tried to do the full outer join on, where you dont get intersecting results. I found out that you can't do full outer joins in mysql but had to do a left join, unioned with a right join. I tried this but don't get the results I wanted at all. I have been stuck for a while now. Can anyone point me in the right direction?
This is what I have so far.
DROP TABLE IF EXISTS Umatable;
DROP TABLE IF EXISTS Johntable;
CREATE TABLE Umatable(title VARCHAR(500));
CREATE TABLE Johntable(title VARCHAR(500));
INSERT INTO Umatable
SELECT m.title
FROM movie m, person p, involved i
WHERE p.name = "Uma Thurman"
AND p.id = i.personid
AND m.id = i.movieiD;
INSERT INTO Johntable
SELECT m.title
FROM movie m, person p, involved i
WHERE p.name = "John Travolta"
AND p.id = i.personid
AND m.id = i.movieiD;
SELECT *
FROM Umatable
LEFT JOIN Johntable ON Umatable.title = Johntable.title
WHERE Johntable.title IS NULL OR Umatable.title IS NULL
UNION
SELECT *
FROM Umatable
RIGHT JOIN Johntable ON Umatable.title = Johntable.title
WHERE Johntable.title IS NULL OR Umatable.title IS NULL
I would do this using aggregation and having:
select i.movieId
from involved i join
person p
on p.id = i.personId
group by i.movieId
having sum(p.name in ('John Travolta', 'Uma Thurman')) = 1;
A count(*) inside a correlated subquery will work:
select *
from movie m
where 1 = (select count(*)
from involved i
join person p
on p.ID = i.personID
and p.name IN ('John Travolta', 'Uma Thurman')
where i.movieID = m.ID)
SQLFiddle Demo

SQL Statement - Too dumb to figure it out

I have a working knowledge of SQL Server along with the ability to perform most basic queries. However, I'm stuck and needs some help with this one. I have 6 related tables from which I need to derive a set of data.
Tables are as follows:
MTMeterReadings mr
Actual
GroupID
MeterID
CreateDate
MTMeterReadingGroups mg
MeterReadingGroupID
MeterSourceID
EquipmentID
MTMeterSources ms
MeterSourceID
Description
MTMeters m
MeterID
Description
SCEquipment eq
EquipmentID
CustomerID
ARCustomers c
CustomerID
CustomerName
My desired result set is to show the following data for each Actual record in the MTMeterReadins table where mr.CreateDate > 'mm/dd/yyy':
mr.actual | mr.CreateDate | ms.description | e.EquipmentID | c.CustomerName
So far, I've been able to create a query with everything I need except c.CustomerName, but just can't seem to take it all the way (I can be JOIN challenged at times).
Any help with this is greatly appreciated.
I apologize, but I didn't know if the query I already had would be helpful or not.
Here is what I have that yields everything I want except customer name:
SELECT
mg.EquipmentID,
CAST(mr.Actual AS decimal(12, 0)) AS Meter,
CAST(mr.CreateDate AS DATE) AS MeterDate,
ms.MeterSource, m.Description
FROM
MTMeterReadings AS mr
INNER JOIN
MTMeterReadingGroups AS mg ON mr.MeterReadingGroupID = mg.MeterReadingGroupID
INNER JOIN
MTMeterSources AS ms ON mg.MeterSourceID = ms.MeterSourceID
INNER JOIN
MTMeters AS m ON mr.MeterID = m.MeterID
WHERE
(mr.CreateDate >= '01/01/2014') AND (mr.CreateDate <= '02/20/2015')
ORDER BY
MeterDate DESC, mg.EquipmentID, m.Description
However, every attempt that I have made to add CustomerName yields a multiple of the records that I have in the mr table. I can't tell exactly what my error is, but I'm assuming it is an incorrect join. Maybe simple for someone with a bigger SQL brain than me, but this is far from being inside my core knowledge base as I learned SQL from a SAMS "Teach Yourself SQL in 10 Minutes" book.
You are missing additional 2 joins:
SELECT mg.EquipmentID, CAST(mr.Actual AS decimal(12, 0)) AS Meter, CAST(mr.CreateDate AS DATE) AS MeterDate, ms.MeterSource, m.Description, ar.CustomerName
FROM MTMeterReadings AS mr INNER JOIN
MTMeterReadingGroups AS mg ON mr.MeterReadingGroupID = mg.MeterReadingGroupID INNER JOIN
MTMeterSources AS ms ON mg.MeterSourceID = ms.MeterSourceID INNER JOIN
MTMeters AS m ON mr.MeterID = m.MeterID
INNER JOIN SCEquipment eq on mg.EquipmentID = eq.EquipmentID
INNER JOIN ARCustomers ar on eq.CustomerID = ar.CustomerID
WHERE (mr.CreateDate >= '01/01/2014') AND (mr.CreateDate <= '02/20/2015')
ORDER BY MeterDate DESC, mg.EquipmentID, m.Description
It should be as simple as this:
SELECT mg.EquipmentID,
CAST(mr.Actual AS DECIMAL(12, 0)) AS Meter,
CAST(mr.CreateDate AS DATE) AS MeterDate,
ms.MeterSource,
m.Description
c.CustomerName
FROM MTMeterReadings AS mr INNER JOIN
MTMeterReadingGroups AS mg ON mr.MeterReadingGroupID = mg.MeterReadingGroupID INNER JOIN
MTMeterSources AS ms ON mg.MeterSourceID = ms.MeterSourceID INNER JOIN
MTMeters AS m ON mr.MeterID = m.MeterID INNER JOIN
SCEquipment AS e ON mg.EquipmentID = e.EquipmentID INNER JOIN
ARCustomers AS c ON e.CustomerID = c.CustomerID
WHERE (mr.CreateDate BETWEEN '01/01/2014' AND '02/20/2015')
ORDER BY MeterDate DESC,
mg.EquipmentID,
m.Description
But that's assuming that there are no possible outer joins and that every relation you want has at least one record.
Also, note that if mr.CreateDate is a datetime you will miss times on 2/20/2015 after midnight.

SQL query not show needed result

I have a SQL query where I have to query three tables (some of them twice) and I do not get the result I need:
I need to search in 'articles' for a search string ('tennis') and lookup a second table 'orderdetails' for these articles.
The hits show how much was ordered.
Now I need to check if these items were already delivered.
So I look up table 'orders' for the 'orderdetails' and look in the same table if these orders have a 'delivery'. 'orders' adn 'delivery' have a field which shows what kind it is.
So I have to check if a 'delivery' was forwarded by an 'order'.
Next check if this 'delivery' includes the 'article' and sum up the delivered articles.
If the number of delivered articles is lower than the number of ordered articles I want to show this record.
So far it works besides these items:
- [SOLVED] thanks to HLGEM 'orders' without a 'delivery' are not shown at all
- [SOLVED] 'orders' with the same amount as 'delivery' are shown but i don't want them to.
Here is what I have so far:
PrO: Process Order
PrD: Process Delivery
a: ArticleItem
p: processOrderItem
d: deliveryItem
[updated the code]
SELECT
a.Articlenumber AS Article,
PrO.Number AS Order,
PrD.Number AS Delivery,
p.Amount AS Orderamount,
SUM(d.Amount) AS Deliveryamount,
(p.Amount - Deliveryamount) AS OpenAmount
FROM Article AS a
INNER JOIN ProcessesDetails AS p
ON (a.ArticleNumber = p.Article)
AND LEFT(p.Order, 3) = 'OR-'
INNER JOIN Processes as PrO
ON PrO.Number = p.Order
AND TEXTSEARCH('Delivery:' IN PrO.Forwarded)
LEFT JOIN Processes as PrD
ON PrO.Nummer = PrD.ForwardedFrom
AND LEFT(PrD.Number,3) = 'DE-'
INNER JOIN ProcessesDetails as d
ON PrD.Number = d.Order
AND d.Article = p.Article
WHERE (a.Categorie = 'tennis')
GROUP BY(Article)
Adding the following line solved the second problem:
HAVING Deliveryamount < Orderamount
SELECT
a.Articlenumber AS Article,
PrO.Number AS Order,
PrD.Number AS Delivery,
p.Amount AS Orderamount,
SUM(d.Amount) AS Deliveryamount,
(p.Amount - Deliveryamount) AS OpenAmount
FROM Article AS a
INNER JOIN ProcessesDetails AS p ON (a.ArticleNumber = p.Article)
INNER JOIN Processes as PrO ON PrO.Number = p.Order
LEFT JOIN Processes as PrD ON PrO.Nummer = PrD.ForwardedFrom AND LEFT(PrD.Number,3) = 'DE-'
INNER JOIN ProcessesDetails as d ON PrD.Number = d.Order
WHERE (a.Categorie = 'tennis')
AND LEFT(p.Order, 3) = 'OR-'
AND TEXTSEARCH('Delivery:' IN PrO.Forwarded)AND d.Article = p.Article
GROUP BY(Article)
This will fix your left join problem.
I have no Idea what is this line in the where condition:
AND TEXTSEARCH('Delivery:' IN PrO.Forwarded)
I don't think that textsearch function exist in mysql, so try this:
SELECT
a.Articlenumber AS Article,
PrO.Number AS Order,
PrD.Number AS Delivery,
p.Amount AS Orderamount,
SUM(d.Amount) AS Deliveryamount,
(p.Amount - Deliveryamount) AS OpenAmount
FROM Article AS a
INNER JOIN ProcessesDetails AS p ON (a.ArticleNumber = p.Article)
INNER JOIN Processes as PrO ON PrO.Number = p.Order
LEFT JOIN Processes as PrD ON PrO.Nummer = PrD.ForwardedFrom
INNER JOIN ProcessesDetails as d ON PrD.Number = d.Order
WHERE (a.Categorie = 'tennis')
AND LEFT(p.Order, 3) = 'OR-'
AND PrO.Forwarded like '%Delivery:%'
AND LEFT(PrD.Number,3) = 'DE-'
AND d.Article = p.Article
GROUP BY(Article)
try using AND PrO.Forwarded like '%Delivery:%' instead of AND TEXTSEARCH('Delivery:' IN PrO.Forwarded)
The first problem is possibly related to these two lines:
LEFT JOIN Processes as PrD ON PrO.Nummer = PrD.ForwardedFrom
and
AND LEFT(PrD.Number,3) = 'DE-'
because the left join effectively has NULL values if there is no delivery there is no way that the PrD.Number can start with 'DE-'. It's possible that a where clause like:
AND (PrD.Number is null OR LEFT(PrD.Number,3) = 'DE-')
Might solve the first part of your question. Not sure about the second part of the question. I can't figure out where you're doing the numeric comparison.

left join with specific conditions help please

am having a problem constructing a query
here is simplified tables structure
3 tables
Event [Event_id , Event_name]
Event_files [Event_id(FK) , File_id(FK)]
Uploaded_Files[File_id , File_type, File_path]
we mainly have 2 file types
image = 2
document = 4
what am trying to do is to get the events along with their images (if they have an image )
am trying to do this with this Query
select e.id, e.name,uf.id as file_id,uf.path
from event e
left join event_file ef on ef.event_id = e.id
left join uploaded_file uf ON ef.file_id = uf.id
i know that i need to apply a condition but each time i do in the where or ON there is always problem with the Query
for example if i apply :
left join uploaded_file uf ON ef.file_id = uf.id AND (uf.type = 2 )
it will still return 2 records for the events that has both image and file one of them with file_path null .
on the other hand if i do the following :
where (uf.id is null OR (uf.id is not null AND uf.type=2))
the events with only files and no image will not be returned any more
is there is solution please ?
thanks in advance
SELECT e.id, e.name, f.file_id AS file_id, f.path
FROM event e
LEFT JOIN
(
SELECT ef.event_id, uf.id AS file_id, uf.path
FROM event_file ef
INNER JOIN uploaded_file uf ON ef.file_id = uf.id AND uf.type = 2
) f ON f.event_id = e.id
This should do (untested.)
The reason you're getting the empty record is because you only specify the uf.type condition on the uploaded_file table, which imposes nothing on the left join for event_file.