I'm trying to figure out if it's possible to use a local varaible inside a mysql statement.
I've a statement that looks something like this (unrelated fields, joins and conditions have been filtered):
SELECT
m.id,
IF (!m.subscribers_only OR m.user_id = ? OR !ISNULL(mu.media_id) OR !ISNULL(us.user_id), 1, 0) AS has_access
FROM media m
LEFT JOIN media_user mu ON mu.user_id = ? AND m.id = mu.media_id
LEFT JOIN user_subscriptions us ON us.user_id = ? AND m.user_id = us.user_subscriber_to_id
All 3 variable is the same variable, so instead of having to bind the parameter 3 times, is it possible to set a local variable in the statement and only having to do 1 bind.
I've considered using SET #current_user = 1 and then using #current_user, but as I'm using PDO, it's not possible to run two statements in one query, and I'm worried how the interaction is when combined with a load balancer.
Edit to show how I'm printing #paramter_test:
SELECT
m.id,
#parameter_test,
IF (!m.subscribers_only OR m.user_id = #parameter_test OR !ISNULL(mu.media_id) OR !ISNULL(us.user_id), 1, 0) AS has_access
FROM media m
JOIN (SELECT #parameter_test:= 1) a
LEFT JOIN media_user mu ON mu.user_id = #parameter_test AND m.id = mu.media_id
LEFT JOIN user_subscriptions us ON us.user_id = #parameter_test AND m.user_id = us.user_subscriber_to_id
Try something like:
SELECT
m.id,
IF (!m.subscribers_only OR m.user_id = #parameter_test OR !ISNULL(mu.media_id) OR
!ISNULL(us.user_id), 1, 0) AS has_access
FROM media m
JOIN (SELECT #parameter_test:= 1) a
LEFT JOIN media_user mu ON mu.user_id = #parameter_test AND m.id = mu.media_id
LEFT JOIN user_subscriptions us ON us.user_id = #parameter_test AND m.user_id =
us.user_subscriber_to_id
You can always create a variable inside a sql statement as long as it's declared before it's use.
In this case you won't be using placeholder ? since those are replaced by parameter.
Related
I have a Date/Time parameter to my report:
But when I run my query, I get no results:
SELECT HD_QUEUE.NAME as qname, HD_TICKET.ID, HD_TICKET.CREATED, HD_TICKET.TIME_CLOSED, CUSTOMER.FULL_NAME as custfullname,
HD_STATUS.NAME as statname, HD_TICKET.TITLE, left(ASSIGNEE.FULL_NAME, 40) as assignee,
HD_PRIORITY.NAME as pname, HD_CATEGORY.NAME as catname
FROM HD_TICKET
INNER JOIN HD_QUEUE
ON HD_TICKET.HD_QUEUE_ID = HD_QUEUE.ID
INNER JOIN USER CUSTOMER
ON HD_TICKET.SUBMITTER_ID=CUSTOMER.ID
INNER JOIN USER ASSIGNEE
ON HD_TICKET.OWNER_ID=ASSIGNEE.ID
INNER JOIN HD_STATUS
ON (HD_TICKET.HD_STATUS_ID=HD_STATUS.ID)
AND (HD_TICKET.HD_QUEUE_ID=HD_STATUS.HD_QUEUE_ID)
INNER JOIN HD_PRIORITY
ON HD_TICKET.HD_PRIORITY_ID = HD_PRIORITY.ID
and HD_TICKET.HD_QUEUE_ID = HD_PRIORITY.HD_QUEUE_ID
INNER JOIN HD_CATEGORY
ON HD_TICKET.HD_CATEGORY_ID = HD_CATEGORY.ID
and HD_TICKET.HD_QUEUE_ID = HD_CATEGORY.HD_QUEUE_ID
left join ASSET on ASSET.ID = HD_TICKET.ASSET_ID
left join ASSET_DATA_6 on ASSET.ASSET_DATA_ID = ASSET_DATA_6.ID
WHERE (HD_STATUS.NAME = 'Closed'
AND HD_TICKET.TIME_CLOSED < #date_param);
What am I doing wrong?
MySQL does not allow named parameters. Use '?' instead of '#date_param' in the query.
WHERE (HD_STATUS.NAME = 'Closed'
AND HD_TICKET.TIME_CLOSED < ?;
Then check the Dataset Properties and make sure the '?' is associated with the value of your parameter:
looking for a bit of help here if possible?
I have the following query:-
On or database we have a table called Linkfile, in this table are "Types" all beginning with "YG". I need to return those rows that do not have the type of "YG8" but just cannot seem to do it. I know ill need to use a sub query but am stuck!
This is my code and the fields I need to return. I just need to only show those that do not have the lk.type of "YG8"
select distinct l.description, p.displayname AS Temp, p.compliance_status As 'Compliant', lk.displayname, lk.type
from event e
inner join organisation o on e.organisation_ref = o.organisation_ref
inner join opportunity opp on e.opportunity_ref = opp.opportunity_ref
inner join event_role ev on ev.event_ref = e.event_ref
inner join address a on a.address_ref = opp.address_ref
inner join person p on ev.person_ref = p.person_ref
inner join lookup l on p.responsible_team = l.code
inner join person_type pt on p.person_ref = pt.person_ref
inner join linkfile lk on lk.parent_object_ref = pt.person_ref
where o.displayname LIKE '%G4S%' and p.compliance_category = '$016'
and lk.type like 'YG%' and l.code_type = '2'
and a.displayname LIKE '%MOJ%'
and pt.status = 'A'
order by l.description, p.displayname, lk.type
Use below query :
select distinct l.description, p.displayname AS Temp, p.compliance_status As 'Compliant', lk.displayname, lk.type,lk.parent_object_ref
from event e
inner join organisation o on e.organisation_ref = o.organisation_ref
inner join opportunity opp on e.opportunity_ref = opp.opportunity_ref
inner join event_role ev on ev.event_ref = e.event_ref
inner join address a on a.address_ref = opp.address_ref
inner join person p on ev.person_ref = p.person_ref
inner join lookup l on p.responsible_team = l.code
inner join person_type pt on p.person_ref = pt.person_ref
left join (select displayname, type,parent_object_ref from linkfile where lk.type like 'YG8%' )lk on lk.parent_object_ref = pt.person_ref
where o.displayname LIKE '%G4S%' and p.compliance_category = '$016' and lk.parent_object_ref is null
and l.code_type = '2'
and a.displayname LIKE '%MOJ%'
and pt.status = 'A'
order by l.description, p.displayname, lk.type;
I've used left join on linkfile with type like 'YG8%' and fetching the only records which are not matched
I think you can just replace the
lk.type like 'YG%'
with the following:
(lk.type >= 'YG' and lk.type <'YG8') or (lk.type > 'YG8' and lk.type <='YGZ')
this should accomplish what you are trying to do and also avoid using "like" which is less efficient (assuming you have an index on lk.type, at least).
You may refine this a bit by knowing which are the possible values of lk.type of course. I.e. what are the extremes for the YG "subtype"? YG00-YG99? YG-YGZ?
(Be especially careful if you may have YG81 or YG87 for example, because then my clause will not work properly... on the other hand if your YG subtype can have values like YG34 it would have been better to use YG08 instead of YG8)
First, the table names and layouts:
Here are my desired results:
Here is the 'got ya' (trick) I guess..
I will only be passing a (dynamic) imis_id/user_id (col names currently not matching on one table)...
So a lookup (select) will need to be done on the relations table for that passed in (dynamic) id.. and where current_org = 1.
This will get/give me the target org_id in which I need to grab all user info (that are associated with the org_id).. and all org details.
Here is one weak/failed attempt: (it uses a hardcoded org_id) which is not valid.. I need to ONLY pass in the user_id/imis_id.. and where current_org = 1 to get the target org_id.
SELECT genealogy_orgs.org_id, genealogy_orgs.org_name,
genealogy_relations.user_id, genealogy_relations.relation_type, genealogy_relations.start_year, genealogy_relations.end_year,
genealogy_users.imis_id, genealogy_users.full_name
FROM genealogy_orgs
INNER JOIN genealogy_relations ON genealogy_orgs.org_id = genealogy_relations.org_id
INNER JOIN genealogy_users ON genealogy_relations.user_id = genealogy_users.imis_id
WHERE genealogy_orgs.org_id = '84864';
Here is another failed attempt (which only returns 1 row).. but uses the correct criteria:
SELECT
genealogy_relations.org_id,
genealogy_relations.user_id, genealogy_relations.relation_type, genealogy_relations.start_year, genealogy_relations.end_year,
genealogy_users.imis_id, genealogy_users.full_name,
genealogy_orgs.org_name
FROM genealogy_relations
INNER JOIN genealogy_orgs ON genealogy_relations.org_id = genealogy_orgs.org_id
INNER JOIN genealogy_users ON genealogy_relations.user_id = genealogy_users.imis_id
WHERE genealogy_relations.user_id = '00003' AND genealogy_relations.current_org = '1';
At this point, I'm not even sure what I need to search for? Is this where a 'sub-query/sub-select' comes into play?
My MySQL-fu is limited to very direct/plain-jane query types. This is getting to be more advanced than I am used to.
You need to join the genealogy_relations table with itself on org_id:
SELECT o.*, u.*
FROM genealogy_relations r1
JOIN genealogy_relations r2 ON r2.org_id = r1.org_id
JOIN genealogy_orgs o ON o.org_id = r2.org_id
JOIN genealogy_users u ON u.imis_id = r2.user_id
WHERE r1.user_id = '00003'
AND r1.current_org = '1'
Remove the genealogy_relations.user_id = '00003' from the query and it should work
SELECT
genealogy_relations.org_id,
genealogy_relations.user_id, genealogy_relations.relation_type, genealogy_relations.start_year, genealogy_relations.end_year,
genealogy_users.imis_id, genealogy_users.full_name,
genealogy_orgs.org_name
FROM genealogy_relations
INNER JOIN genealogy_orgs ON genealogy_relations.org_id = genealogy_orgs.org_id
INNER JOIN genealogy_users ON genealogy_relations.user_id = genealogy_users.imis_id
WHERE genealogy_relations.current_org = '1';
I have checked several threads on here and cannot find the answer to my question....
I am trying to do a mysql query with multiple tables and left join the last table. It does not like the left join and gives me no results when I include it. Any help is greatly appreciated :)
(I am using Joomla)
query = "SELECT DISTINCT u.id as uid, CONCAT(u.first_name,' ',u.last_name) as name1,
u.grad as grad, u.opt_out as opt_out
FROM #__bl_teams as t, #__bl_regions as r, #__users as u
LEFT JOIN #__bl_paid as pd ON pd.u_id = u.id
WHERE u.team_id = t.id AND u.team_id != '' AND u.s_id = $sid
AND ((t.id = $tid)OR($tid=0)) AND (t.id IN ($teamsfull))
AND ( (t.id IN(".$tc_teams."))OR(".$tc_id." = 0))
AND ((r.id = ".$mid.")OR(".$mid." = 0))
AND ((r.s_id = ".$sid.")OR(".$mid." = 0))
AND ( (FIND_IN_SET(t.id,r.teams) )OR(".$mid." = 0) )
AND u.id NOT IN($paidrows) AND u.id NOT IN ($rsrows) GROUP BY u.id";
$db->setQuery($query, $pageNav->limitstart, $pageNav->limit);
$rows50 = $db->loadObjectList();
You are mixing old-style joins and new style joins. That is your problem. The table aliases aren't recognized throughout the from statement, the way you expect them to be. Buried in the documentation is this warning:
However, the precedence of the comma operator is less than of INNER
JOIN, CROSS JOIN, LEFT JOIN, and so on. If you mix comma joins with
the other join types when there is a join condition, an error of the
form Unknown column 'col_name' in 'on clause' may occur. Information
about dealing with this problem is given later in this section.
Simple rule: Never use commas in the from clause.
So, rewrite your query using explicit joins and that will fix the problem.
I don't know the ctual tables, but this query is too long and will have unexpected results results. Anyways, Left join the other tables too.
query = "SELECT DISTINCT u.id as uid, CONCAT(u.first_name,' ',u.last_name) as name1,
u.grad as grad, u.opt_out as opt_out
FROM #__users as u
LEFT JOIN #__bl_paid as pd ON pd.u_id = u.id
LEFT JOIN #__bl_teams as t ON t.u_id = u.id
LEFT JOIN #__bl_regions as r ON r.u_id = u.id
WHERE u.team_id != ''
AND u.s_id = $sid
AND ((t.id = $tid)
OR($tid=0))
AND (t.id IN ($teamsfull))
AND ( (t.id IN(".$tc_teams."))
OR(".$tc_id." = 0))
AND ((r.id = ".$mid.")
OR(".$mid." = 0))
AND ((r.s_id = ".$sid.")
OR(".$mid." = 0))
AND ( (FIND_IN_SET(t.id,r.teams) )
OR(".$mid." = 0) )
AND u.id NOT IN($paidrows)
AND u.id NOT IN ($rsrows)
GROUP BY u.id";
I have the following SQL:
$queryString = "
SELECT
iR.lastModified,
d.*,
c2.title as stakeholderTitle,
u.username as authorUsername,
c.title as authorContactName,
GROUP_CONCAT(iR.stakeholderRef) AS participants
FROM
informationRelationships iR,
contacts c2
INNER JOIN
debriefs d ON
d.id = iR.linkId
LEFT JOIN
users u ON
u.id = iR.author
LEFT JOIN
contacts c ON
c.ref = u.contactId
LEFT JOIN
debriefs d2 ON
d2.stakeholder = c2.ref
WHERE
(
iR.clientRef = '$clientRef' OR
iR.contactRef = '$contactRef'
)
AND
iR.projectRef = '$projectRef' AND
iR.type = 'Debrief'
GROUP BY
iR.linkId
ORDER BY
d.dateOfEngagement
";
notice how I require 2 different bits of data for the the contacts table.
So at one point, I need to match
c.ref = u.contactId
This will return one bit of information
but I also need a completely different grouping:
d2.stakeholder = c2.ref
Problem is that the title is the column i'm interested in for both:
c2.title as stakeholderTitle,
...
c.title as authorContactName
How do I go about doing this?
My current try is returning:
Error: Unknown column 'iR.linkId' in 'on clause'
I'm not sure I really understand what is happening here:
how to join two tables on common attributes in mysql and php?
EDIT::::---ANSWERED--zerkms
$queryString = "
SELECT
iR.lastModified,
d.*,
c2.title as stakeholderTitle,
u.username as authorUsername,
c.title as authorContactName,
GROUP_CONCAT(iR.stakeholderRef) AS participants
FROM
informationRelationships iR
INNER JOIN
debriefs d ON
d.id = iR.linkId
INNER JOIN
contacts c2 ON
d.stakeholder = c2.ref
LEFT JOIN
users u ON
u.id = iR.author
LEFT JOIN
contacts c ON
c.ref = u.contactId
WHERE
(
iR.clientRef = '$clientRef' OR
iR.contactRef = '$contactRef'
)
AND
iR.projectRef = '$projectRef' AND
iR.type = 'Debrief'
GROUP BY
iR.linkId
ORDER BY
d.dateOfEngagement
";
By re-ordering my query I have managed to get both columns in... Thanks zerkms!
You cannot mix implicit joins and explicit joins in a single query in mysql.
So
FROM informationRelationships iR,
contacts c2
should be rewritten to
FROM informationRelationships iR
INNER JOIN contacts c2 ON ...
Do not use cartesian product and joins in the same query (not subquery), here, use only joins (CROSS JOIN is the same as cartesian product).