SQL VIEW WITH JOINS - mysql

I have 3 tables
Node table - Nodeid, Node relationship id(NodeRelID)
Node relationship table - id, Nodeid, Node Link id
Eventstatus Tabel - id, Nodeid, Node Status.
I want to create a view where it displays each node's id and the status of the node related to it. I have done that here;
CREATE VIEW `view_alarm` AS
select `node`.`NodeID` AS `NodeID`,`eventstatus`.`EventID` AS `EventID`
from ((`node` join `node_relationship`) join `eventstatus`)
where ((`node`.`NodeRelID` = `node_relationship`.`id`) and (`node_relationship`.`Node_LinkID` = `eventstatus`.`NodeID`));
Now I would like to retrieve any nodes that do not have a relationship and automatically give them a 0 in the place of the relationship status and i would like this stored in the same table so i have attempted this via a case statement in the view. Like so:
CREATE view `view_alarm` AS select
`node`.`NodeID` AS `NodeID`,
(case when (`node_relationship`.`Node_LinkID` = `eventstatus`.`NodeID`) then `eventstatus`.`EventID`
when (`node_relationship`.`Node_LinkID` <> `eventstatus`.`NodeID`) then `eventstatus`.`EventID` '0' end) AS `EventID`
from ((`node` join `node_relationship`) join `eventstatus`)
where (`node`.`NodeRelID` = `node_relationship`.`id`);
Can someone point me in the right direction.

Use outer joins in a recursive join
FROM Node n
LEFT JOIN Node_Relationship nr1
ON n.key = nr.key
LEFT JOIN Node_Relationship nr2
ON n.key = nr2.Key
AND n.key IS NULL
Use it in your case:
CASE
WHEN nr2.[key] IS NOT NULL THEN 0

Related

Using SELECT clause in ELSE part of SQL query?

I have two tables.
Table number 1 (Lab_test): with integer columns named labtest_id (pk) and project_no. Second table (Project) has two columns, first column named project_id (int) and second column project_name (string). Also I have two parameters which are passed to the query.
I have to make a query which will extract labtest_id and proj_num. proj_num have to be obtained in following way: if Lab_test.project_no is not null, take this value, else go to referencing table Project and take project_name.
I tried with bunch of combinations using SQL CASE IF-THEN-ELSE statements, but no luck:
SELECT lab.labtest_id, proj_num,
FROM Lab_test lab
(CASE
WHEN lab.project_no IS NOT NULL THEN lab.project_no
ELSE (SELECT proj.project_name
FROM Project proj
WHERE proj.project_id = lab.project_no)
) AS proj_num
WHERE lab.status = 'DONE' AND lab.user_id = 436
You can use left join and coalesce() to replace the case when expression that you've used to check null
SELECT lab.labtest_id, coalesce(lab.project_no,proj.project_name) as proj_num
FROM Lab_test lab
left join Project proj on proj.p,roject_id = lab.project_no
where lab.status = 'DONE' AND lab.user_id = 436
if Lab_test.project_no is not null, take this value, else go to referencing table Project and take project_name.
I don't believe you. I think you have the logic backwards -- use the referenced table if it is available. Otherwise use the number.
That would suggest:
SELECT l.labtest_id, COALESCE(p.project_name, l.project_no) as proj_num
FROM Lab_test l LEFT JOIN
Project p
ON p.p,roject_id = l.project_no
WHERE l.status = 'DONE' AND l.user_id = 436;
If the project_no is a number, then you might have a type conversion problem. If that is an issue:
SELECT l.labtest_id,
COALESCE(p.project_name, CAST(l.project_no as CHAR)) as proj_num
FROM Lab_test l LEFT JOIN
Project p
ON p.p,roject_id = l.project_no
WHERE l.status = 'DONE' AND l.user_id = 436;

Editing the Results of a MySQL View

I'm trying to create a view in my relational MySQL database that will allow the user to update football match results from one (virtual) table within phpMyAdmin.
I have the view all setup visually how I want, and I am able to edit most of the fields, except I am getting error messages. If, for instance, I update the number of goals scored for a team, I get the following error messages shown below. It will still update that record, however, because if I refresh the page, that particular entry will change to what I entered.
I am aware that you cannot have a primary key on a view, but in terms of indexing, shouldn't the existing relationships be sufficient for this to work?
Another issue is updating the referee field. As this is a concatenated field (first_name + last_name), I cannot attempt to update it from the view.
This is my database structure:
This is the code for my view:
CREATE VIEW `view1_match_main` AS
SELECT
`match_main`.`match_id` AS `Match ID`,
`season`.`season` AS `Season`,
`match_status`.`status_no` AS `Status`,
`match_main`.`date_time` AS `Date`,
`c1`.`club_name` AS `Home Club`,
`mr1`.`goal` AS `Home Goals`,
`mr2`.`goal` AS `Away Goals`,
`c2`.`club_name` AS `Away Club`,
CONCAT(`referee`.`referee_first_name`,
' ',
`referee`.`referee_last_name`) AS `Referee`,
`stadium`.`stadium_name` AS `Stadium`,
`match_main`.`attendance` AS `Attendance`,
`match_main`.`bbc_url` AS `BBC URL`,
`match_main`.`sky_url` AS `Sky URL`
FROM
((((((((`match_main`
LEFT JOIN `referee` ON ((`match_main`.`referee_id` = `referee`.`referee_id`)))
LEFT JOIN `season` ON ((`match_main`.`season_id` = `season`.`season_id`)))
LEFT JOIN `match_status` ON ((`match_main`.`status_id` = `match_status`.`status_id`)))
LEFT JOIN `match_result` `mr1` ON (((`mr1`.`match_id` = `match_main`.`match_id`)
AND (`mr1`.`home_team` = 1))))
LEFT JOIN `club` `c1` ON ((`c1`.`club_id` = `mr1`.`club_id`)))
LEFT JOIN `match_result` `mr2` ON (((`mr2`.`match_id` = `match_main`.`match_id`)
AND (`mr2`.`home_team` = 0))))
LEFT JOIN `club` `c2` ON ((`c2`.`club_id` = `mr2`.`club_id`)))
LEFT JOIN `stadium` ON ((`c1`.`stadium_id` = `stadium`.`stadium_id`)))
ORDER BY `season`.`season` DESC , `match_main`.`date_time` , `c1`.`club_name`

MySQL Query - Object Queuing Based on Object Property to Skill Mapping

Okay, so I know the title is a bit cryptic so I'll do what I can to explain the "problem" I have and the solution I am currently using.
Problem:
An 'object' of work needs to be distributed to the apropriate user based on said object's properties.
The idea is that there is an object of work has properties. Those properties are mapped to skills. A user has skills and is able to work on an object which is within the user's skillset.
There are several [three] property definitions and I currently have the following table structures.
|-- Object to Property Set 1 -- Property Set 1 to Skill --|
Object Table -|-- Object to Property Set 2 -- Property Set 2 to Skill --|-- User Skill -- User Table
|-- Object to Property Set 3 -- Property Set 3 to Skill --|
The query may be a bit easier to understand:
SELECT counts.object_id,
COUNT(DISTINCT counts.object_skill) object_skill_count,
COUNT(DISTINCT counts.user_skill) user_skill_count
FROM
(SELECT object.object_id,
sp.skill_id object_skill,
us.skill_id user_skill
FROM object_table object
LEFT JOIN object_property op ON op.object_id = object.object_id
LEFT JOIN skill_property sp ON sp.property_id = op.property_id
LEFT JOIN user_skill us ON us.skill_id = sp.skill_id
AND us.active = 1
AND us.user_id = {$userid} -- <=- inserted from a PHP script
AND object.state = 1
UNION SELECT object.object_id,
sf.skill_id object_skill,
us.skill_id user_skill
FROM object_table object
LEFT JOIN object_flag obf ON obf.object_id = object.object_id
LEFT JOIN skill_flag sf ON sf.flag_id = obf.flag_id
LEFT JOIN user_skill us ON us.skill_id = sf.skill_id
AND us.active = 1
AND us.user_id = {$userid} -- <=- inserted from a PHP script
AND object.state = 1
UNION SELECT object.object_id,
svf.skill_id object_skill,
us.skill_id user_skill
FROM object_table object
LEFT JOIN object_creator oc ON oc.creator_id = object.creator_id
LEFT JOIN skill_creator sc ON sc.flag_id = oc.flag_id
LEFT JOIN user_skill us ON us.skill_id = sc.skill_id
AND us.active = 1
AND us.user_id = {$userid} -- <=- inserted from a PHP script
AND object.state = 1) counts
GROUP BY counts.object_id
Here we get a count of all the skills an object as well as count the number of skills the user has on that same object. If the two counts match, we know the user can work on the object. If the object's skill count exceeds the user's count, the object is beyond the user's capabilities and will not be assigned to that user.
While the above query works, it slows significantly when thrown at a large[r] table. Would like to know if there is a better way of doing things. And, since the internet is filled with amazing people, here we are.
Retroactive Update:
The Left joins in this case are there because objects can have no properties. This equates to the count 0-0 and thus makes the object workable by anyone.
It looks ok. Conditions placed on data joins instead of where clause, no order by's.
Possible options:
1) Check for missing indexes
http://basitaalishan.com/2013/03/13/find-missing-indexes-using-sql-servers-index-related-dmvs/
2) Change 'left joins' to 'inner joins'
INNER JOIN vs LEFT JOIN performance in SQL Server
3) Use 'UNION ALL' instead of 'Union'
performance of union versus union all

MySQL SubQuery Conditional

I am trying to build a rather complex view in MySQL and want to do a conditional, but it sems always to fail.
My view (simplified) is
Select entry AS Entry, ,(select count(`poitems`.`entry`) AS `count(poitems.entry)` from `poitems` where (`poitems`.`PurchaseOrder` = `purchaseorder`.`entry`)) AS `TotalEntries`, from purchase orders
this is OK but what I am trying to do is add something like
if ((select count(`poitems`.`entry`) = 0),'query.png',NULL) AS Queryflag
or just test the value of TotalEntries.
Help appreciated! Thanks!
I'm not 100% sure on the names of the columns in purchaseorder or poitems tables but the following should get you headed in the right direction:
select t.Entry,
case when t.TotalEntries > 0 then 'query.png' else null end as Queryflag
from
(
select po.entry as Entry,
count(*) as TotalEntries
from purchaseorder po
left outer join poitems poi on poi.purchaseorder = po.entry
group by po.entry
) t;

LINQ AssociateWith for data context generating LEFT JOIN instead of INNER JOIN

I'm trying to create an "AssociateWith" data load option for my context to filter rows that the current user has access to. My simple data model is as such:
Tables
UserPermissions
PK: ID
FK: RelatedUserID nullable
FK: RelatedItemID not nullable
Users
PK: ID
Items
PK: ID
FK: RelatedCategoryID not nullable
Categories
PK: ID
On my datacontext, I'm trying to do something like:
//dbContext is my LINQ context
//current_user_id is the id of my current logged in user
var dlo = new DataLoadOptions();
//issue->UsersPermissions is one->many relationship
// if I omit this LoadWith line, no associatewith filter
// is created in the generated sql code
dlo.LoadWith<Items>(i=>i.UserPermissions);
dlo.AssociateWith<Items>(i=>
i.UserPermissions.Where(p=>
p.RelatedUserID.HasValue && p.RelatedUserID.Value == current_users_id));
dbContext.LoadOptions = dlo;
Everything seems reasonable to me, but the query generated in SQL looks like this:
SELECT [t0].[ID], [t1].[ID] AS [ID2], [t1].[RelatedUserID], [t1].[RelatedItemID]
(SELECT COUNT(*)
FROM [dbo].[UserPermissions] AS [t2]
WHERE (([t2].[RelatedUserID] = #p0)) AND ([t2].[RelatedItemID] = [t0].[ID])
) AS [value]
FROM [dbo].[Items] AS [t0]
LEFT OUTER JOIN [dbo].[UserPermissions] AS [t1] ON ([t1].[RelatedUserID] = #p0)
AND
([t1].[RelatedItemID] = [t0].[ID])
ORDER BY [t0].[ID], [t1].[ID]
How can I force an INNER JOIN instead of the LEFT OUTER JOIN? Am I modeling my relationship incorrectly on the backend?
Thanks for any help.
MMAS
LINQ to SQL generates the LEFT OUTER JOIN simply because UserPermissions.RelatedUserID column is nullable. The underlying LINQ provider just isn't 'smart' enough to further optimize that query to a simple INNER JOIN. I don't think there is anything you can do about this.