I have the following (simplified) query:
SELECT
u.idnumber AS user_idnumber,
sst_status.value AS scorm_status,
sst_starttime.value AS scorm_starttime,
sst_duration.value AS scorm_duration,
sst_score.value AS scorm_score,
u.id as uid,
s.id as scormid,
ss.id as ssid
FROM {user} u
LEFT JOIN {prog_user_assignment} prua ON prua.userid = u.id
LEFT JOIN {prog} pr ON prua.programid = pr.id
LEFT JOIN {prog_courseset} prcs ON prcs.programid = pr.id
LEFT JOIN {prog_courseset_course} prcsc ON prcsc.coursesetid = prcs.id
LEFT JOIN {course} c ON prcsc.courseid = c.id
LEFT JOIN {scorm} s ON s.id = cm.instance
LEFT JOIN {scorm_scoes} ss ON ss.scorm = s.id
LEFT JOIN {scorm_scoes_track} sst_status
ON sst_status.userid = u.id
AND sst_status.scormid = ss.scorm
AND sst_status.element = 'cmi_core.lesson_status'
AND sst_status.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_starttime
ON sst_starttime.userid = u.id
AND sst_starttime.scormid = ss.scorm
AND sst_starttime.element = 'x.start.time'
AND sst_starttime.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_duration
ON sst_duration.userid = u.id
AND sst_duration.scormid = ss.scorm
AND sst_duration.element = 'cmi.core.total_time'
AND sst_duration.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_score
ON sst_score.userid = u.id
AND sst_score.scormid = ss.scorm
AND sst_score.element = 'cmi.core.score.raw'
AND sst_score.scoid = ss.id
WHERE u.id IN([SOME_EXAMPLE_IDS_HERE]) AND u.deleted = 0
group by u.idnumber, c.id
Now the problem is that without the GROUP BY clause, some of the records have values for scorm_status, scorm_starttime etc. However, these contain duplicates. But, with the group by statement, only NULL values are returned for these columns. Does anyone have a clue on how to resolve this?
Using GROUP_CONCAT and SUBSTRING_INDEX:-
SELECT
u.idnumber AS user_idnumber,
SUBSTRING_INDEX(GROUP_CONCAT(sst_status.value), ',', 1) AS scorm_status,
SUBSTRING_INDEX(GROUP_CONCAT(sst_starttime.value), ',', 1) AS scorm_starttime,
SUBSTRING_INDEX(GROUP_CONCAT(sst_duration.value), ',', 1) AS scorm_duration,
SUBSTRING_INDEX(GROUP_CONCAT(sst_score.value), ',', 1) AS scorm_score,
u.id as uid,
s.id as scormid,
ss.id as ssid
FROM {user} u
LEFT JOIN {prog_user_assignment} prua ON prua.userid = u.id
LEFT JOIN {prog} pr ON prua.programid = pr.id
LEFT JOIN {prog_courseset} prcs ON prcs.programid = pr.id
LEFT JOIN {prog_courseset_course} prcsc ON prcsc.coursesetid = prcs.id
LEFT JOIN {course} c ON prcsc.courseid = c.id
LEFT JOIN {scorm} s ON s.id = cm.instance
LEFT JOIN {scorm_scoes} ss ON ss.scorm = s.id
LEFT JOIN {scorm_scoes_track} sst_status
ON sst_status.userid = u.id
AND sst_status.scormid = ss.scorm
AND sst_status.element = 'cmi_core.lesson_status'
AND sst_status.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_starttime
ON sst_starttime.userid = u.id
AND sst_starttime.scormid = ss.scorm
AND sst_starttime.element = 'x.start.time'
AND sst_starttime.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_duration
ON sst_duration.userid = u.id
AND sst_duration.scormid = ss.scorm
AND sst_duration.element = 'cmi.core.total_time'
AND sst_duration.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_score
ON sst_score.userid = u.id
AND sst_score.scormid = ss.scorm
AND sst_score.element = 'cmi.core.score.raw'
AND sst_score.scoid = ss.id
WHERE u.id IN([SOME_EXAMPLE_IDS_HERE]) AND u.deleted = 0
group by u.idnumber, c.id
This is getting the first non null values of these fields. Note that this is relying on the fields not containing commas (but easy enough to specify a different separator for the GROUP_CONCAT). You can specify an order for the GROUP_CONCAT to get your preferred value if required.
Here is a very simplified version of your query:
select u.idnumber AS user_idnumber, sst_status.value AS scorm_status,
sst_starttime.value AS scorm_starttime, sst_duration.value AS scorm_duration,
sst_score.value AS scorm_score, u.id as uid, s.id as scormid, ss.id as ssid
. . .
group by u.idnumber, c.id;
You will notice that most of the columns in the select are not in the group by. This is using a (mis)feature of MySQL and would not generally be allowed in other databases.
What MySQL does is it chooses an abritrary value from one of the rows for the result. The idea is that this works nicely if the column is constant for the group. But, it doesn't usually work as expected in other circumstances.
If you want a non-NULL value, then you can use max() or min() to get the biggest or smallest value.
For instance:
min(sst_status.value) AS scorm_status
and so on.
Related
the tables
the query
SELECT
u.ID AS _ctbUserId,
umRef.meta_value AS _ctbRef,
umThumbnail.meta_value AS _ctbThumbnail,
umShortText.meta_value AS _ctbShortText,
umLanguages.meta_value AS _ctbLanguages,
umKeywords.meta_value AS _ctbKeywords,
umNickname.meta_value AS _ctbNickname,
umChatSessionGuid.meta_value AS _ctbChatSessionGuid,
umChatSessionStatus.meta_value AS _ctbChatSessionStatus,
umChatSessionStatusVisual.meta_value AS _ctbChatSessionStatusVisual,
umChatSessionMaxUsers.meta_value AS _ctbChatSessionMaxUsers,
umChatSessionLastChanged.meta_value AS _ctbChatSessionLastChanged,
umChatSessionTpm.meta_value AS _ctbChatSessionTpm,
umChatEnableCam.meta_value AS _ctbChatEnableCam,
umMessenger.meta_value AS _ctbMessenger,
umMessengerTokensPerMessage.meta_value AS _ctbMessengerTokensPerMessage,
umCallSessionStatus.meta_value AS _ctbCallSessionStatus,
umCallSessionStatusVisual.meta_value AS _ctbCallSessionStatusVisual,
umCallSessionStatusLastChanged.meta_value AS _ctbCallSessionLastChanged,
umCallSessionTpm.meta_value AS _ctbCallSessionTpm
FROM chattabai_users AS u
LEFT JOIN chattabai_usermeta AS umRole ON umRole.user_id = u.ID AND umRole.meta_key = "chattabai_capabilities"
LEFT JOIN chattabai_usermeta AS umRef ON umRef.user_id = u.ID AND umRef.meta_key = "_ctbRef"
LEFT JOIN chattabai_usermeta AS umThumbnail ON umThumbnail.user_id = u.ID AND umThumbnail.meta_key = "_ctbThumbnail"
LEFT JOIN chattabai_usermeta AS umShortText ON umShortText.user_id = u.ID AND umShortText.meta_key = "_ctbShortText"
LEFT JOIN chattabai_usermeta AS umLanguages ON umLanguages.user_id = u.ID AND umLanguages.meta_key = "_ctbLanguages"
LEFT JOIN chattabai_usermeta AS umKeywords ON umKeywords.user_id = u.ID AND umKeywords.meta_key = "_ctbKeywords"
LEFT JOIN chattabai_usermeta AS umNickname ON umNickname.user_id = u.ID AND umNickname.meta_key = "_ctbNickname"
LEFT JOIN chattabai_usermeta AS umChatSessionGuid ON umChatSessionGuid.user_id = u.ID AND umChatSessionGuid.meta_key = "_ctbChatSessionGuid"
LEFT JOIN chattabai_usermeta AS umChatSessionStatus ON umChatSessionStatus.user_id = u.ID AND umChatSessionStatus.meta_key = "_ctbChatSessionStatus"
LEFT JOIN chattabai_usermeta AS umChatSessionStatusVisual ON umChatSessionStatusVisual.user_id = u.ID AND umChatSessionStatusVisual.meta_key = "_ctbChatSessionStatusVisual"
LEFT JOIN chattabai_usermeta AS umChatSessionMaxUsers ON umChatSessionMaxUsers.user_id = u.ID AND umChatSessionMaxUsers.meta_key = "_ctbChatSessionMaxUsers"
LEFT JOIN chattabai_usermeta AS umChatSessionLastChanged ON umChatSessionLastChanged.user_id = u.ID AND umChatSessionLastChanged.meta_key = "_ctbChatSessionLastChanged"
LEFT JOIN chattabai_usermeta AS umChatSessionTpm ON umChatSessionTpm.user_id = u.ID AND umChatSessionTpm.meta_key = "_ctbChatSessionTpm"
LEFT JOIN chattabai_usermeta AS umChatEnableCam ON umChatEnableCam.user_id = u.ID AND umChatEnableCam.meta_key = "_ctbChatEnableCam"
LEFT JOIN chattabai_usermeta AS umMessenger ON umMessenger.user_id = u.ID AND umMessenger.meta_key = "_ctbMessenger"
LEFT JOIN chattabai_usermeta AS umMessengerTokensPerMessage ON umMessengerTokensPerMessage.user_id = u.ID AND umMessengerTokensPerMessage.meta_key = "_ctbMessengerTokensPerMessage"
LEFT JOIN chattabai_usermeta AS umCallSessionStatus ON umCallSessionStatus.user_id = u.ID AND umCallSessionStatus.meta_key = "_ctbCallSessionStatus"
LEFT JOIN chattabai_usermeta AS umCallSessionStatusVisual ON umCallSessionStatusVisual.user_id = u.ID AND umCallSessionStatusVisual.meta_key = "_ctbCallSessionStatusVisual"
LEFT JOIN chattabai_usermeta AS umCallSessionStatusLastChanged ON umCallSessionStatusLastChanged.user_id = u.ID AND umCallSessionStatusLastChanged.meta_key = "_ctbCallSessionLastChanged"
LEFT JOIN chattabai_usermeta AS umCallSessionTpm ON umCallSessionTpm.user_id = u.ID AND umCallSessionTpm.meta_key = "_ctbCallSessionTpm"
WHERE umRole.meta_value LIKE 'a: 1: {s: 8:\"employee\";b:1;}'
AND (umChatSessionStatus.meta_value REGEXP 'online|inConversation|pause|offline' OR umCallSessionStatus.meta_value REGEXP 'online|inConversation|pause|offline')
AND umLanguages.meta_value REGEXP ''
AND umKeywords.meta_value REGEXP ''
ORDER BY FIELD(umChatSessionStatus.meta_value, 'online,inConversation,pause,offline'), FIELD(umCallSessionStatus.meta_value, 'online,inConversation,pause,offline')
LIMIT 0, 20
This is from a Wordpress database. As Wordpress uses usermeta data this is the way of storing the user data. ( https://developer.wordpress.org/plugins/users/working-with-user-metadata/ )
This query takes up to 1500MS to run on with a limit of 20 profiles. Any recommendations to improve this?
Output
I have the following query and would like to convert it to using a left outer join instead of a not in to see if it would run faster that way. It's currently taking this query about 40 seconds to run on our database. I'm not familiar enough with using outer joins for this type of thing to convert it myself.
select
c.contact_id as contact_id,
c.orgid as organization_id,
c.first_name as first_name,
c.last_name as last_name,
a.address_state as state
from cnx_contact as c
inner join cnx_address as a on c.home_address_uid = a.address_uid
where a.address_state = 'OH'
and (c.orgid = 45 or c.orgid = 55)
and c.contact_id NOT IN (
select pc.contact_id
from cnx_contact as c
inner join cnx_address as a on c.home_address_uid = a.address_uid
inner join cnx_contact_group_participant as gp on c.contact_id = gp.contact_id
inner join cnx_contact_participant_role as cr on gp.participant_role_uid = cr.participant_role_uid
inner join cnx_contact_group as cg on gp.group_uid = cg.group_uid
inner join cnx_contact_group_participant as pgp on cg.primary_participant_uid = pgp.participant_uid
inner join cnx_contact as pc on pgp.contact_id = pc.contact_id
where (c.orgid = 45 or c.orgid = 55)
and cr.name = 'Applicant'
);
select
c.columns
from cnx_contact as c
inner join cnx_address as a on c.home_address_uid = a.address_uid
LEFT JOIN
(Subquery goes here) x
ON x.contact _id = c.contact_id
where a.participant_state = 'OH'
and c.orgid IN(45,55)
and x.contact_id IS NULL;
I've got the query below that's pulling data from a number of tables to create an update:
UPDATE en_inter.subscribers_data AS sd
inner join en_inter.list_subscribers AS ls on sd.subscriberid = ls.subscriberid
LEFT JOIN (
SELECT pd1.email_address,COUNT(pd1.email_address) AS NumDowns
FROM email.papr_down pd1
INNER JOIN email.papr_data pd2 on pd1.paper_id = pd2.id
INNER JOIN email.papr_subj ps on ps.id = pd2.subject
INNER JOIN email.papr_exam pe on pe.id = pd2.exam
INNER JOIN email.papr_levl pl on pl.id = pd2.level
WHERE pd2.exam = 1
and pd2.level = 4
GROUP BY email_address
) AS downs ON downs.email_address = ls.emailaddress
SET sd.data = ifnull(downs.NumDowns,1)
WHERE sd.fieldid = 33;
It works fine but when there are plenty of records in papr_down then it takes ages to process. Any ideas about how it can be optimized?
What I think is the join between the emailAddress is the issue here, you can try out with the join with the Id's.
If you provide us the screen shot of the below query ::
EXPLAIN Select * from
en_inter.subscribers_data AS sd
inner join en_inter.list_subscribers AS ls on sd.subscriberid = ls.subscriberid
LEFT JOIN (
SELECT pd1.email_address,COUNT(pd1.email_address) AS NumDowns
FROM email.papr_down pd1
INNER JOIN email.papr_data pd2 on pd1.paper_id = pd2.id
INNER JOIN email.papr_subj ps on ps.id = pd2.subject
INNER JOIN email.papr_exam pe on pe.id = pd2.exam
INNER JOIN email.papr_levl pl on pl.id = pd2.level
WHERE pd2.exam = 1
and pd2.level = 4
GROUP BY email_address
) AS downs ON downs.email_address = ls.emailaddress
WHERE sd.fieldid = 33
As I know we should use joins only for the columns which are preset in SELECT clause and for other joins we should implement using WHERE clause
Please try following query:
UPDATE en_inter.subscribers_data AS sd
inner join en_inter.list_subscribers AS ls
on sd.subscriberid = ls.subscriberid
LEFT JOIN (
SELECT pd1.email_address,COUNT(pd1.email_address) AS NumDowns
FROM email.papr_down AS pd1
INNER JOIN email.papr_data AS pd2 on pd1.paper_id = pd2.id
WHERE
email.papr_exam.id in (select exam from email.papr_data where exam = 1)
AND
email.papr_levl.id in (select level from email.papr_data where level = 4 )
AND
email.papr_subj.id in (select subject from email.papr_data)
GROUP BY email_address
) AS downs ON downs.email_address = ls.emailaddress
SET sd.data = ifnull(downs.NumDowns,1)
WHERE sd.fieldid = 33;
I can not execute this at my machine since i don't have the schema
I need to do a LEFT JOIN with IF/ELSE, this is my query:
IF (M.idArtVar=null,
LEFT JOIN ArtMaga G
ON (G.idMagazzino = V.idMagazzino AND G.idArticolo = M.idArticolo),
LEFT JOIN ArtMaga G
ON (G.idMagazzino = V.idMagazzino AND G.idArticolo = M.idArticolo AND
G.idArtVar = M.idArtVar)
)
But it doesn't work.
I also tried like this:
LEFT JOIN ArtMaga AM
ON IF(M.idArtVar IS NULL,
(AM.idMagazzino = TM.idMagazzino AND AM.idArticolo = A.idArticoli),
(AM.idMagazzino = TM.idMagazzino AND AM.idArtVar = M.idArtVar))
But this query is too slow.
How can I do?
Thanks.
EDIT: This is full query:
SELECT F.Codice AS "CodiceFornitore", F.RagioneSociale AS "RagioneSocialeFornitore", A.ArticoloFornitore, C.Descrizione AS CatDes, S.Descrizione AS Settore, U.Sigla AS Um, U2.Sigla AS Um2, A.Moltiplicatore AS Molt, A.Collo, TM.
dMagazzino, M.idArtVar, AM.Esistenza, AM.Disponibilita, AM.QtaImpegnata, AM.QtaOrdinata, TM.TipoSoggetto, TM.idSoggetto, ST.DataMovimento, MC.Codice, ST.Quantita, ST.Prezzo, ST.Sconti, M.idMagaRigMov
FROM MagaRigMov M
LEFT JOIN Articoli A ON A.idArticoli = M.idArticolo
LEFT JOIN UnMisura U ON U.idUnMisura = A.idUnMisura1
LEFT JOIN UnMisura U2 ON U2.idUnMisura = A.idUnMisura2
LEFT JOIN Iva I ON I.idIva = A.idIva
LEFT JOIN Settori S ON S.idSettori = A.idSettore
LEFT JOIN Fornitori F ON F.idFornitori = A.idFornitore
LEFT JOIN ArtCategorie C ON C.idArtCategorie = A.idArtCategoria
LEFT JOIN MagaTesMov TM ON TM.idMagaTesMov = M.idMagaTesMov
LEFT JOIN STORICO ST ON (ST.idSoggetto = TM.idSoggetto AND ST.TipoSoggetto = TM.TipoSoggetto AND ST.idArticolo = M.idArticolo)
LEFT JOIN MagaCausali MC ON MC.idMagaCausali = ST.idMagaCausale
LEFT JOIN ArtMaga AM ON IF(M.idArtVar IS NULL,(AM.idMagazzino = TM.idMagazzino AND AM.idArticolo = A.idArticoli),
(AM.idMagazzino = TM.idMagazzino AND AM.idArtVar = M.idArtVar))
This query is too slow.. but works..
You can't use an IF to make a conditional join. Because IF is not part of the SELECT syntax and even if it was (like CASE expressions) it wouldn't be allowed to be used like this. You can move the logic to the ON statement though:
LEFT JOIN ArtMaga G
ON (G.idMagazzino = V.idMagazzino AND G.idArticolo = M.idArticolo)
AND M.idArtVar IS NULL
OR (G.idMagazzino = V.idMagazzino AND G.idArticolo = M.idArticolo AND
G.idArtVar = M.idArtVar)
AND M.idArtVar IS NOT NULL
which can be simplified to:
LEFT JOIN ArtMaga G
ON (G.idMagazzino = V.idMagazzino AND G.idArticolo = M.idArticolo)
AND (M.idArtVar IS NULL OR G.idArtVar = M.idArtVar)
Also notice that you can't use equality to check if an expression is null.
M.idArtVar = null will never be true because NULL can never be equal to anything (not even to NULL). The way to check if an expression is null is with IS NULL.
Your second query, that words, is using the IF() function of MySQL and seems to be correct (although I see a difference in the code with the first query, the G.idArticolo = M.idArticolo condition has been removed from one part.)
Why a query is slow depends on many factors and using functions on the join conditions can be one of the many. Try the change I suggest above. If it still slow, you'll have to examine the execution plan and the available indexes on the tables.
Just put the condition in the on clause. If is not part of a SQL statement.
SELECT F.Codice AS "CodiceFornitore", F.RagioneSociale AS "RagioneSocialeFornitore",
A.ArticoloFornitore, C.Descrizione AS CatDes, S.Descrizione AS Settore, U.Sigla AS Um, U2.Sigla AS Um2, A.Moltiplicatore AS Molt, A.Collo, TM.
dMagazzino, M.idArtVar, AM.Esistenza, AM.Disponibilita, AM.QtaImpegnata, AM.QtaOrdinata, TM.TipoSoggetto, TM.idSoggetto, ST.DataMovimento, MC.Codice, ST.Quantita, ST.Prezzo, ST.Sconti, M.idMagaRigMov
FROM MagaRigMov M
LEFT JOIN Articoli A ON A.idArticoli = M.idArticolo
LEFT JOIN UnMisura U ON U.idUnMisura = A.idUnMisura1
LEFT JOIN UnMisura U2 ON U2.idUnMisura = A.idUnMisura2
LEFT JOIN Iva I ON I.idIva = A.idIva
LEFT JOIN Settori S ON S.idSettori = A.idSettore
LEFT JOIN Fornitori F ON F.idFornitori = A.idFornitore
LEFT JOIN ArtCategorie C ON C.idArtCategorie = A.idArtCategoria
LEFT JOIN MagaTesMov TM ON TM.idMagaTesMov = M.idMagaTesMov
LEFT JOIN STORICO ST ON (ST.idSoggetto = TM.idSoggetto AND ST.TipoSoggetto = TM.TipoSoggetto AND ST.idArticolo = M.idArticolo)
LEFT JOIN MagaCausali MC ON MC.idMagaCausali = ST.idMagaCausale
LEFT JOIN ArtMaga AM ON (AM.idMagazzino = TM.idMagazzino AND (m.idartVar is NULL and AM.idArtVar = M.idArtVar or AM.idArticolo = A.idArticoli))
I have this query.
SELECT notes.id,enter.name as 'enter_name',step.title as 'flow status',notes.user_name as user_created,notes.created,notes.rel_client_id,td_doc_nr.value_string as 'document number',enter.enter_code,
IF(!ISNULL(td_doc_nr.value_string),
(SELECT GROUP_CONCAT(product_name SEPARATOR ',') from notes d
join note_bundles b on b.note_id = d.id
join note_products p on p.doc_bundle_id = b.id
join note_product_get_fields f on f.doc_product_id = p.id
join note_product_get_field_data fd on fd.get_field_id = f.id
where d.doc_nr = td_doc_nr.value_string
and value_string ='auto')
,NULL) as test
FROM notes notes
JOIN notes_steps step ON step.id = notes.step_id
JOIN notes_enters enter ON enter.id = notes.enter_id
LEFT JOIN notes_custom_fields tf_doc_nr ON tf_doc_nr.name = 'note_number' AND tf_doc_nr.rel_entity_id = enter.id
LEFT JOIN notes_custom_field_data td_doc_nr ON td_doc_nr.rel_entity_id = notes.id AND
td_doc_nr.field_instance_id = tf_doc_nr.id
WHERE notes.enter_id in (777) AND notes.status = 1
I added this subquery to the 'if statement'
SELECT GROUP_CONCAT(product_name SEPARATOR ',') from nontes d
join note_bundles b on b.note_id = d.id
join note_products p on p.doc_bundle_id = b.id
join note_product_get_fields f on f.doc_product_id = p.id
join note_product_get_field_data fd on fd.get_field_id = f.id
where d.doc_nr = 'G7777777'
and value_string ='auto'
After this I added a new column.
SELECT GROUP_CONCAT(product_name SEPARATOR ','),GROUP_CONCAT(DISTINCT b.msisdn SEPARATOR ',') from notes d
join note_bundles b on b.note_id = d.id
join note_products p on p.doc_bundle_id = b.id
join note_product_get_fields f on f.doc_product_id = p.id
join note_product_get_field_data fd on fd.get_field_id = f.id
where d.doc_nr = 'G7777777'
and value_string ='auto'
It returns two columns.
How can I return two columns?Is it possible? :) Thanks
A subquery inside an IF statement can't return multiple columns. You will need to join the subquery into the results, and pull out the two separate columns individually:
SELECT ...
IF(!ISNULL(td_doc_nr.value_string), sub.one, NULL) as one,
IF(!ISNULL(td_doc_nr.value_string), sub.two, NULL) as two
FROM ...
LEFT JOIN (
SELECT d.doc_nr, GROUP_CONCAT(product_name SEPARATOR ','),GROUP_CONCAT(DISTINCT b.msisdn SEPARATOR ',') from documents d
join document_bundles b on b.document_id = d.id
join document_products p on p.doc_bundle_id = b.id
join document_product_cstm_fields f on f.doc_product_id = p.id
join document_product_cstm_field_data fd on fd.cstm_field_id = f.id
where value_string ='auto'
group by d.doc_nr
) sub on sub.doc_nr = td_doc_nr.value_string
A correlated subquery inside an IF statement can only return 1 column and 1 row, this is why you are getting the error. However, looking over your query the only outer reference inside the subquery is
d.doc_nr = td_doc_nr.value_string
So you do not need actually need a correlated subquery and you can achieve the same result by moving the subquery to a join and grouping by doc_nr within the subquery, which will probably be much more efficient, and it will allow you to return the 2 columns you want:
SELECT tickets.id,
source.name as 'source_name',
flow_stage.title as 'flow status',
tickets.user_name as user_created,
tickets.created,
tickets.rel_client_id,
td_doc_nr.value_string as 'document number',
source.source_code,
IF(!ISNULL(td_doc_nr.value_string), ProductNames, NULL) as test,
d.MSISDNS
FROM tickets tickets
JOIN tickets_flow_stages flow_stage
ON flow_stage.id = tickets.flow_stage_id
JOIN tickets_sources source
ON source.id = tickets.source_id
LEFT JOIN tickets_custom_fields tf_doc_nr
ON tf_doc_nr.name = 'document_number'
AND tf_doc_nr.rel_entity_id = source.id
LEFT JOIN tickets_custom_field_data td_doc_nr
ON td_doc_nr.rel_entity_id = tickets.id
AND td_doc_nr.field_instance_id = tf_doc_nr.id
LEFT JOIN
( SELECT d.Doc_nr,
GROUP_CONCAT(product_name SEPARATOR ',') AS ProductNames,
GROUP_CONCAT(DISTINCT b.msisdn SEPARATOR ',') AS MSISDNS
from documents d
INNER JOIN document_bundles b
ON b.document_id = d.id
INNER JOIN document_products p
ON p.doc_bundle_id = b.id
INNER JOIN document_product_cstm_fields f
ON f.doc_product_id = p.id
INNER JOIN document_product_cstm_field_data fd
ON fd.cstm_field_id = f.id
WHERE value_string ='auto'
GROUP BY d.Doc_nr
) d
ON d.doc_nr = td_doc_nr.value_string
WHERE tickets.source_id IN (114,122,125,129,131)
AND tickets.status = 1