Join with multiple conditions - mysql

my entire query is a bit complex so I'll try to just show what you need to understand my problem, I'm fetching tickets from a data base, it displays the title, the creator, the people in charge of the ticket, and the last updater, for the creator and the people in charge I find their ID in tickets_users.users_id and their type 1 or 2 depending if they are the creator of the ticket or if they are in charge, for the title and all the informations of the ticket itself the table is named tickets now for the users their ID their name etc it's users
So my query looks like that:
SELECT
tickets.id,
tickets.name,
GROUP_CONCAT(
CASE WHEN tickets_users.type = 1 THEN
CONCAT(users.firstname, ' ', users.realname)
END) AS creator,
GROUP_CONCAT(
CASE WHEN tickets_users.type = 1 THEN
CONCAT(tickets_users.users_id)
END) AS creator_id,
GROUP_CONCAT(
CASE WHEN tickets_users.type = 2 THEN
CONCAT(users.firstname, ' ', users.realname)
END) AS in_charge,
GROUP_CONCAT(
CASE WHEN tickets_users.type = 2 THEN
CONCAT(tickets_users.users_id)
END) AS in_charge_id,
tickets.date,
tickets.priority,
tickets.date_mod,
tickets.status,
tickets.users_id_lastupdater,
MAX(CASE WHEN tickets.users_id_lastupdater = users.id
THEN CONCAT(users.firstname, ' ', users.realname)
END) AS last_updater,
tickets.content
FROM
tickets
JOIN tickets_users ON tickets_users.tickets_id = tickets.id
JOIN users ON users.id = tickets_users.users_id
WHERE tickets.id = ?");
My problem is there JOIN users ON users.id = tickets_users.users_id it works well for people in charge and creator, but if someone that is not in charge reply or modify the ticket he will not appear in "last modified by" because the last_updater ID is in the table tickets.
I tried to JOIN with JOIN users ON (users.id = tickets_users.users_id AND , glpi_tickets.users_id_lastupdater) but it didn't work. Any ideas?

ON users.id IN (tickets_users.users_id, tickets.last_updater)
And
You'd need to add the test AND users.id = tickets_users.users_id to
your CASE statements
Worked, thanks eggyal!

Related

How would I constrain my CONCAT statement to just the id from the if statement in MySQL

I've been beating my head against the wall for a while now on this. I've tried following the thought behind Concat in If statement but I can't seem to figure out a way to make my specific need work. I'm now down to a syntax error in my CONCAT statement..'WHERE req.reqCreatedBy = '0' THEN 'Unknown' ELSE users.firstname,' ',users.lastn'. Could anybody give me some help on bringing the first and last name in on this query? I'm at a complete loss.
SELECT req.reqID as Id,
reqDesc.titleText as Title,
req.reqCity as City,
req.reqState as State,
req.areaID as Area,
area.areaname,
reqType.typeTitle as Type,
req.reqCreatedDate as Created,
req.reqEndDate as `End`,
CONCAT((CASE WHERE req.reqCreatedBy = '0' THEN 'Unknown' ELSE users.firstname,' ',users.lastname END))
AS Recruiter
FROM apps_job_request as req
INNER JOIN apps_job_request_description as reqDesc
ON req.reqTitle = reqDesc.titleID
INNER JOIN apps_job_request_type as reqType
ON reqDesc.typeID = reqType.typeID
INNER JOIN `assemble_users`.area AS area
ON area.areaid = req.areaID
INNER JOIN `assemble_users`.users AS users
ON users.username = req.reqCreatedBy
WHERE req.reqID is not null
AND req.reqActive = '1'
If check only one value req.reqCreatedBy, there may be simple IF statement, use CASE for multiple checked values.
SELECT req.reqID as Id,
reqDesc.titleText as Title,
req.reqCity as City,
req.reqState as State,
req.areaID as Area,
area.areaname,
reqType.typeTitle as Type,
req.reqCreatedDate as Created,
req.reqEndDate as `End`,
-- req.reqCreatedBy is '0' OR ''?
IF(req.reqCreatedBy = '0', 'Unknown', CONCAT(users.firstname, ' ', users.lastname)) AS Recruiter
FROM apps_job_request as req
INNER JOIN apps_job_request_description as reqDesc
ON req.reqTitle = reqDesc.titleID
INNER JOIN apps_job_request_type as reqType
ON reqDesc.typeID = reqType.typeID
INNER JOIN `assemble_users`.area AS area
ON area.areaid = req.areaID
INNER JOIN `assemble_users`.users AS users
ON users.username = req.reqCreatedBy
WHERE req.reqID is not null
AND req.reqActive = '1'

MySQL - subquery or joining multiple rows

I got a little struggle with my mysql query. Maybe someone can help me.
Tables:
contacts:
|id|phone|first_name|last_name|email|company|
custom_values:
|id|c_id|custom_field_id|value|
The table custom_values got different custom_field_ids
id 4 = mobile
id 5 = fax
id 20 = 2nd phonenumber
The current query gives me all information from my contacts table.
concat(contacts.first_name, ' ', contacts.last_name, ' - ', contacts.company) as displayname, contacts.phone, contacts.last_name, contacts.first_name, contacts.company, contacts.email
from contacts
Now I want to add the information from the custom_values table to the query above.
Is it possible to add 3 rows, that adds me mobile, fax and the 2nd phonenomber to every contact?
I tried with the next query, but that doesn´t work.
SELECT
concat(contacts.first_name, ' ', contacts.last_name, ' - ', contacts.company) as displayname, contacts.phone, contacts.last_name, contacts.first_name, contacts.company, contacts.email,custom_values.value as mobile
from custom_values
join contacts on custom_values.customized_id = contacts.id
where custom_values.custom_field_id=4
thanks guys.
If you want additional rows, then your approach is fine. However, I think you want additional columns, not additional rows.
One approach is multiple LEFT JOIN:
select concat(c.first_name, ' ', c.last_name, ' - ', c.company) as displayname,
c.phone, c.last_name, c.first_name, c.company, c.email,
cvm.value as mobile,
cvf.value as fax,
cvp2.value as second_phone
from contacts c left join
custom_values cvm
on cvm.customized_id = c.id and
cvm.custom_field_id = 4 left join
custom_values cvf
on cvf.customized_id = c.id and
cvf.custom_field_id = 5 left join
custom_values cvp2
on cvp2.customized_id = c.id and
cvp2.custom_field_id = 20;

How to pivot the following JOIN query

I am attempting to pass data from database to Google charts, however, Google charts has a specific way in which it excepts data. For this reason, I need to change the following output:
to this :
the query for the original output is:
SELECT (select COUNT(projects.funding)from projects where funding > 0)as Funding,
SUM(projects.mreq = 'yes') Mentor_Required,
SUM(projects.tmreq = 'yes') Team_Member_Required
FROM projects INNER JOIN users ON projects.members = users.email
WHERE users.company = 'vit'
The 2 tables are:
projects
users
Would love some guidance on putting pivot on the above query or any better method.
I think you can just do:
SELECT (CASE WHEN p.mreq = 'yes' THEN 'Mentor_Required'
WHEN p.tmreq = 'yes' THEN 'Team_Member_Required'
END) as Funding,
COUNT(*) as cnt
FROM projects p INNER JOIN
users u
ON p.members = u.email
WHERE u.company = 'vit'
GROUP BY Funding;

Selection of user's vote column based on ID

In my public voting database, I have pages and pages_votes tables with structure below:-
Page
Page Votes
i am querying mysql database to get results for all pages with their total sum of positive and negative votes
positive vote is 1, and negative vote is 0.
my query is as below:-
SELECT pages.id, pages.title, COUNT(pv.page_id) AS `total_count`, SUM(pv.vote=1) AS `likes`, SUM(pv.vote=0) AS `dislikes`
FROM `pages`
LEFT JOIN `pages_votes` AS `pv` ON `pages`.`id` = `pv`.`page_id`
GROUP BY `pages`.`id`, `pages`.`title`, `pages`.`slug`, `pages`.`image`
ORDER BY `total_count` DESC;
Results look like this (no issue here):-
Now I want to include a new custom column in this result called 'my_vote', my vote will show me my votes (user_id = 3) as 1 or 0 for like/dislikes if i have voted, and NULL if i have not voted.
There is already a user_id in page_votes table recording which user voted. How do I use that to get votes of a specific user with say ID = 10?
I suggest writing your query with table aliases. Then the answer to your question is a CASE expression:
SELECT p.id, p.title, COUNT(pv.page_id) AS total_count,
SUM(pv.vote =1 ) AS likes, SUM(pv.vote = 0) AS dislikes,
SUM(CASE WHEN pv.vote = 1 AND p.user_id = 3 THEN 1
WHEN pv.vote = 0 AND p.user_id = 3 THEN 0
END) as user_3_vote
FROM pages p LEFT JOIN
pages_votes pv
ON p.id = pv.page_id
GROUP BY p.id, p.title
ORDER BY total_count DESC;
Note that this uses SUM(CASE . . .) rather than SUM( <boolean expression> ). This is important so you can get a NULL value when there is no vote.
will you consider a small change here in your query? to get specified output.
SELECT pages.id, pages.title, COUNT(pv.page_id) AS `total_count`,
SUM(case when pv.vote = 1 then 1 else 0 end) AS `likes`,
SUM(case when pv.vote = 0 then 1 else 0 end) AS `dislikes`
FROM `pages`
LEFT JOIN `pages_votes` AS `pv`
ON `pages`.`id` = `pv`.`page_id`
GROUP BY `pages`.`id`, `pages`.`title`, `pages`.`slug`, `pages`.`image`
ORDER BY `total_count` DESC;

MySQL separate values by user

i have recovered a database from a cmsms website and with Mysql i want to extract all the login information of the front-end users . i work with Heidisql
My problem user_proprerties DB is in this form:
Id UserID Type Data
1 2 email 1#2be.net
2 2 company lorme ipsum
3 2 fname testname
4 5 email& 2#2be.com
5 5 company empty
6 5 fname dolor sir amed
i want the data to be in this form:
Userid email company fname
2 1#2be.be lorem testname
5 2#2be.be emptydolor sir amed
this is the current mysql query that i have
select
cms_module_feusers_users.id,
cms_module_feusers_users.username,
cms_module_feusers_users.createdate,
cms_module_feusers_users.expires,
cms_module_feusers_properties.`data` email
from
cms_module_feusers_users
inner join cms_module_feusers_properties on cms_module_feusers_properties.userid = cms_module_feusers_users.id
where
cms_module_feusers_properties.title = 'email'
But now i'm stuck when i want the company name and fname.
(Fractionally) slower, but cleaner...
SELECT p.userid
, MAX(CASE WHEN type = 'email' THEN data END) email
, MAX(CASE WHEN type = 'company' THEN data END) company
, MAX(CASE WHEN type = 'fname' THEN data END) fname
FROM cms_module_feusers_properties p
GROUP
BY p.userid;
Add a join for each field you need
SELECT
user.id,
user.whatever,
<other stuff from cms_module_feusers_users...>
user_email.`data` as email,
user_company.`data` as company,
<other stuff from cms_module_feusers_properties...>
FROM cms_module_feusers_users user
LEFT JOIN cms_module_feusers_properties user_email ON user_email.userid = user.id AND user_email.title = 'email'
LEFT JOIN cms_module_feusers_properties user_company ON user_company.userid = user.id AND user_company.title = 'company'
<other joins from cms_module_feusers_properties...>
WHERE <conditions related to users...>
You need to use LEFT JOIN because some properties might be missing in cms_module_feusers_properties.
Also this assumes that each property appears at most once for each user.
Try this:
SELECT
cms_module_feusers_users.id,
cms_module_feusers_users.username,
cms_module_feusers_users.createdate,
cms_module_feusers_users.expires,
prop_data.data AS email,
prop_data_company.data AS company,
prop_data_fname.data AS fname
FROM
cms_module_feusers_users
INNER JOIN
(SELECT
*
FROM
cms_module_feusers_properties
WHERE
type = 'email') prop_data ON prop_data.userid = cms_module_feusers_users.id
INNER JOIN
(SELECT
*
FROM
cms_module_feusers_properties
WHERE
type = 'company') prop_data_company ON prop_data_company.userid = cms_module_feusers_users.id
INNER JOIN
(SELECT
*
FROM
cms_module_feusers_properties
WHERE
type = 'fname') prop_data_fname ON prop_data_fname.userid = cms_module_feusers_users.id