GROUP_CONCAT multiple where condition particular data - mysql

Query
(SELECT
pid,
visitdate,
GROUP_CONCAT(tooth, ' - ', problem, ' - ', recomendation SEPARATOR ', <br>')
FROM tbl_finds_d) V
WHERE V.pid='1' AND V.visitdate = '16-03-2020'
TABLE
Want to get WHERE pid=1 AND visitdate=16-03-2020
pid visitdate tooth problem recomendation
1 16-03-2020 13 ASX DFFF
1 16-03-2020 12 JHJ HJLP
2 12-03-2020 14 JKB IJLHJ
UPDATE (copied from the comment)
SELECT *
FROM pendingtreatment A
INNER JOIN tbl_finds_m B ON B.pid = '$pid'
AND B.visitdate = '$visitdate'
INNER JOIN treatmentadviced C ON C.pid = '$pid'
AND C.visitdate = '$visitdate'
INNER JOIN treatmentlist D ON D.pid = '$pid'
AND D.visitdate = '$visitdate'
INNER JOIN tbl_appointments E ON E.pid = '$pid'
AND E.visitdate = '$visitdate'
INNER JOIN ( SELECT pid,
visitdate,
GROUP_CONCAT(tooth, ' - ', problem, ' - ', recomendation SEPARATOR ', <br>')
FROM tbl_finds_d V
WHERE V.pid='$pid'
AND V.visitdate = '$visitdate') F
WHERE A.pid = '$pid'
AND A.visitdate = '$visitdate'

Related

Reduce multiple queries for reporting

I am trying to make a query for a sales report, the code I have works excellent in the aspect that it returns the correct result, however I think it can be greatly improved since I am using multiple queries to generate the columns "Total_Productos", "Total_Servicios " and "Total", I have tried some ways to adjust it but I would like to hear some advice, I attach the code and the result it shows
SELECT f.numero, f.fecha, CONCAT(c.nombre, ' ', c.apellido) AS Cliente,
(SELECT GROUP_CONCAT(' x', CONVERT(fp2.cantidad, CHAR(10)), ' ', nombre) AS Product
FROM facturas_productos fp2
INNER JOIN productos ON productos.codigo = fp2.productos_codigo
WHERE fp2.facturas_numero = fp.facturas_numero) AS Productos,
TRUNCATE((SELECT SUM(fp2.cantidad * productos.precio_venta) AS T_Producto
FROM facturas_productos fp2
INNER JOIN productos ON productos.codigo = fp2.productos_codigo
WHERE fp2.facturas_numero = fp.facturas_numero), 2) AS Total_Productos,
(SELECT GROUP_CONCAT(CONCAT(' x', CONVERT(fs2.cantidad, CHAR(10)), ' ', nombre))
FROM facturas_servicios fs2
INNER JOIN servicios ON servicios.codigo = fs2.servicios_codigo
WHERE fs2.facturas_numero = fs.facturas_numero) AS Servicios,
TRUNCATE((SELECT SUM(fs2.cantidad * servicios.precio) AS T_Servicio
FROM facturas_servicios fs2
INNER JOIN servicios ON servicios.codigo = fs2.servicios_codigo
WHERE fs2.facturas_numero = fs.facturas_numero), 2) AS Total_Servicios,
TRUNCATE((SELECT SUM(fs2.cantidad * servicios.precio) AS T_Servicio
FROM facturas_servicios fs2
INNER JOIN servicios ON servicios.codigo = fs2.servicios_codigo
WHERE fs2.facturas_numero = fs.facturas_numero) +
(SELECT SUM(fp2.cantidad * productos.precio_venta) AS T_Producto
FROM facturas_productos fp2
INNER JOIN productos ON productos.codigo = fp2.productos_codigo
WHERE fp2.facturas_numero = fp.facturas_numero), 2) AS Total
FROM facturas f
INNER JOIN clientes c ON c.ID = f.clientes_ID
INNER JOIN facturas_productos fp ON fp.facturas_numero = f.numero
INNER JOIN facturas_servicios fs ON fs.facturas_numero = f.numero
WHERE f.fecha BETWEEN "2023-01-01" AND "2023-02-04"
GROUP BY f.numero, fp.facturas_numero, fs.facturas_numero, f.fecha, c.nombre, c.apellido
ORDER BY f.numero ASC;
Result from the query above:
I tried to take from the previous queries the values to calculate the total, however it gave me another unexpected result (generated an error/wrong value), i.e:
(SELECT GROUP_CONCAT(CONCAT(' x', CONVERT(fs2.cantidad, CHAR(10)), ' ', nombre)), fs2.cantidad * servicios.precio AS Monto
FROM facturas_servicios fs2
INNER JOIN servicios ON servicios.codigo = fs2.servicios_codigo
WHERE fs2.facturas_numero = fs.facturas_numero) AS Servicios
generates: Error Code: 1241. Operand should contain 1 column(s)
More info: I created the database from a diagram using forward engineer and not from scripts (still learning at university)
Database EER Diagram
If you are running MySQL >= 8.0.14, you can move your correlated sub-queries to lateral derived tables -
SELECT f.numero, f.fecha, CONCAT(c.nombre, ' ', c.apellido) AS Cliente,
fp.Productos, fp.Total_Productos,
fs.Servicios, fs.Total_Servicios,
IFNULL(fs.Total_Servicios, 0) + IFNULL(fp.Total_Productos, 0) AS Total
FROM facturas f
INNER JOIN clientes c ON c.ID = f.clientes_ID
LEFT JOIN LATERAL (
SELECT
GROUP_CONCAT('x', fp2.cantidad, ' ', nombre SEPARATOR ', ') AS Productos,
SUM(fp2.cantidad * productos.precio_venta) AS Total_Productos
FROM facturas_productos fp2
INNER JOIN productos ON productos.codigo = fp2.productos_codigo
WHERE fp2.facturas_numero = f.numero
) fp ON 1 = 1
LEFT JOIN LATERAL (
SELECT
GROUP_CONCAT('x', fs2.cantidad, ' ', nombre SEPARATOR ', ') AS Servicios,
SUM(fs2.cantidad * servicios.precio) AS Total_Servicios
FROM facturas_servicios fs2
INNER JOIN servicios ON servicios.codigo = fs2.servicios_codigo
WHERE fs2.facturas_numero = f.numero
) fs ON 1 = 1
WHERE f.fecha BETWEEN '2023-01-01' AND '2023-02-04'
ORDER BY f.numero ASC;
I have changed the joins to LEFT JOIN LATERAL as I assume it is possible for an invoice to contain products but not services, and vice versa.
An alternative approach, which does not require MySQL >= 8.0.14, is to aggregate all the products and services in their derived tables, instead of doing the lateral join -
SELECT f.numero, f.fecha, CONCAT(c.nombre, ' ', c.apellido) AS Cliente,
fp.Productos, fp.Total_Productos,
fs.Servicios, fs.Total_Servicios,
IFNULL(fs.Total_Servicios, 0) + IFNULL(fp.Total_Productos, 0) AS Total
FROM facturas f
INNER JOIN clientes c ON c.ID = f.clientes_ID
LEFT JOIN (
SELECT
fp.facturas_numero,
GROUP_CONCAT('x', fp.cantidad, ' ', nombre SEPARATOR ', ') AS Productos,
SUM(fp.cantidad * productos.precio_venta) AS Total_Productos
FROM facturas_productos fp
INNER JOIN productos ON productos.codigo = fp.productos_codigo
GROUP BY fp.facturas_numero
) fp ON f.numero = fp.facturas_numero
LEFT JOIN (
SELECT
fs.facturas_numero,
GROUP_CONCAT('x', fs.cantidad, ' ', nombre SEPARATOR ', ') AS Servicios,
SUM(fs.cantidad * servicios.precio) AS Total_Servicios
FROM facturas_servicios fs
INNER JOIN servicios ON servicios.codigo = fs.servicios_codigo
GROUP BY fs.facturas_numero
) fs ON f.numero = fs.facturas_numero
WHERE f.fecha BETWEEN '2023-01-01' AND '2023-02-04'
ORDER BY f.numero ASC;
This may be a little bit faster when retrieving all invoices but will probably be slower when retrieving a small subset of a large number of invoices.
And here's a db<>fiddle

Slow MySQL Query When Run As A Procedure

If I run this query directly in PHPMyAdmin, it returns 13420 rows in 0.2091 second, but if I run the exact same query as a stored procedure, it returns the same amount of row but it takes forever and sometimes the SQL server returns an out of memory exception.
I'm at a total loss - any advice would be welcome, because I can't work out why this slows everything down?!
SELECT
el.UID as LUID,
se.UID as DUID,
el.event_title,
el.event_synopsis,
se.behind_the_scenes,
se.sub_event_title,
se.event_eventDateAndTime,
se.event_eventDateAndTimeEnd,
el.event_confirmed,
el.event_active,
(
SELECT GROUP_CONCAT(sp2.color SEPARATOR ',')
FROM setup__spaces sp2
LEFT JOIN events__assigned_spaces eas2 ON ( eas2.space_id = sp2.UID )
LEFT JOIN events__events_list el2 ON (el2.UID = eas2.event_id)
WHERE el2.UID = el.UID
) as spaceColors,
(
SELECT GROUP_CONCAT(sp2.name SEPARATOR ', ')
FROM setup__spaces sp2
LEFT JOIN events__assigned_spaces eas2 ON ( eas2.space_id = sp2.UID )
LEFT JOIN events__events_list el2 ON (el2.UID = eas2.event_id)
WHERE el2.UID = el.UID
) as spaceNames,
(
SELECT GROUP_CONCAT(sp2.UID SEPARATOR ',')
FROM setup__spaces sp2
LEFT JOIN events__assigned_spaces eas2 ON ( eas2.space_id = sp2.UID )
LEFT JOIN events__events_list el2 ON (el2.UID = eas2.event_id)
WHERE el2.UID = el.UID
) as spaceIds,
(
SELECT GROUP_CONCAT(t.UID SEPARATOR ',')
FROM setup__tags t
LEFT JOIN events__assigned_tags eat ON ( eat.tag_id = t.UID )
LEFT JOIN events__events_list el2 ON (el2.UID = eat.event_id)
WHERE el2.UID = el.UID
) as tagIds,
(
SELECT GROUP_CONCAT(t.tag_name SEPARATOR ', ')
FROM setup__tags t
LEFT JOIN events__assigned_tags eat ON ( eat.tag_id = t.UID )
LEFT JOIN events__events_list el2 ON (el2.UID = eat.event_id)
WHERE el2.UID = el.UID
) as tagNames
FROM events__events_list el
INNER JOIN events__sub_events se ON (el.UID = se.event_masterEvent)
WHERE ((el.event_active='1') OR (el.event_active='0' AND el.event_confirmed = '1'))
AND el.company_uid = sp_company_uid
With thanks to #Akina for pointing me in the right direction, I found help from the following places:
stackoverflow.com - Selecting multiple columns/fields in MySQL subquery
geeksengine.com - How to use subquery in JOIN operation in MySQL
Here's the revised code that's now lightning fast!
SELECT
el.UID as LUID,
se.UID as DUID,
el.event_title,
el.event_synopsis,
se.behind_the_scenes,
se.sub_event_title,
se.event_eventDateAndTime,
se.event_eventDateAndTimeEnd,
el.event_confirmed,
el.event_active,
tags.names as tagNames,
tags.ids as tagIds,
spaces.names as spaceNames,
spaces.colors as spaceColors,
spaces.ids as spaceIds
FROM events__events_list el
INNER JOIN events__sub_events se ON (el.UID = se.event_masterEvent)
LEFT JOIN (
SELECT
el3.UID as el2uid,
GROUP_CONCAT(s.name SEPARATOR ', ') as names,
GROUP_CONCAT(s.color SEPARATOR ',') as colors,
GROUP_CONCAT(s.UID SEPARATOR ',') as ids
FROM setup__spaces as s
LEFT JOIN events__assigned_spaces eas ON ( eas.space_id = s.UID )
LEFT JOIN events__events_list el3 ON ( el3.UID = eas.event_id )
GROUP BY el3.UID
) as spaces on spaces.el2uid = el.UID
LEFT JOIN (
SELECT
el2.UID as el2uid,
GROUP_CONCAT(t.tag_name SEPARATOR ', ') as names,
GROUP_CONCAT(t.UID SEPARATOR ',') as ids
FROM setup__tags as t
LEFT JOIN events__assigned_tags eat ON ( eat.tag_id = t.UID )
LEFT JOIN events__events_list el2 ON ( el2.UID = eat.event_id )
GROUP BY el2.UID
) as tags on tags.el2uid = el.UID
WHERE ((el.event_active='1') OR (el.event_active='0' AND el.event_confirmed = '1'))
AND el.company_uid = sp_company_uid

How to do a Query on SQL Server 2008 R2 using a subquery / function on GROUP BY

When I execute this query, it works fine:
SELECT
pr.pr_nombre , cl.cl_nomcorto,
mc_cant * dbo.tipo_cambio(cr.mo_id,3,mc_fecha)/0.951 as Interes,
mc_cant * dbo.tipo_cambio(cr.mo_id,3,mc_fecha)/0.951*.049 as WH,
(select pr_id from dbo.nonplusultra(cr.pr_id) where pr_renew_ref is null) as Agrupador
FROM movcuentas mc
inner join corridas cr on mc.cr_id = cr.cr_id
inner join clientes cl on cr.cl_id = cl.cl_id
inner join prestamos pr on cr.pr_id = pr.pr_id
WHERE (mc_concepto = 'Amort Int') AND (tm_id = 3) AND MONTH(mc_fecha) = 2 AND YEAR(mc_fecha) = 2017
ORDER BY pr.pr_nombre
I get this:
Query results
Now I need to show it adding columns "Interes" and "WH" on records with same "Agrupador", something like this:
SELECT
pr.pr_nombre , cl.cl_nomcorto,
sum(mc_cant * dbo.tipo_cambio(cr.mo_id,3,mc_fecha)/0.951) as Interes,
sum(mc_cant * dbo.tipo_cambio(cr.mo_id,3,mc_fecha)/0.951*.049) as WH,
(select pr_id from dbo.nonplusultra(cr.pr_id) where pr_renew_ref is null) as Agrupador
FROM movcuentas mc
inner join corridas cr on mc.cr_id = cr.cr_id
inner join clientes cl on cr.cl_id = cl.cl_id
inner join prestamos pr on cr.pr_id = pr.pr_id
WHERE (mc_concepto = 'Amort Int') AND (tm_id = 3) AND MONTH(mc_fecha) = 2 AND YEAR(mc_fecha) = 2017
GROUP BY pr.pr_nombre , cl.cl_nomcorto, (select pr_id from dbo.nonplusultra(cr.pr_id) where pr_renew_ref is null)
ORDER BY pr.pr_nombre
And I get this error message:
Msg 144, Level 15, State 1, Line 12
Cannot use an aggregate or a subquery in an expression used for the group by list of a GROUP BY clause.
Any help will be welcome.
Can you make use of CTE here?
;WITH CTE as
(
SELECT
pr.pr_nombre , cl.cl_nomcorto,
mc_cant * dbo.tipo_cambio(cr.mo_id,3,mc_fecha)/0.951 as Interes,
mc_cant * dbo.tipo_cambio(cr.mo_id,3,mc_fecha)/0.951*.049 as WH,
(select pr_id from dbo.nonplusultra(cr.pr_id) where pr_renew_ref is null) as Agrupador
FROM movcuentas mc
inner join corridas cr on mc.cr_id = cr.cr_id
inner join clientes cl on cr.cl_id = cl.cl_id
inner join prestamos pr on cr.pr_id = pr.pr_id
WHERE (mc_concepto = 'Amort Int') AND (tm_id = 3) AND MONTH(mc_fecha) = 2 AND YEAR(mc_fecha) = 2017
ORDER BY pr.pr_nombre
)
select pr_nombre,cl_nomcorto,sum(Interes),sum(WH),Agrupador
from CTE
group by pr_nombre,cl_nomcorto,Agrupador
order by pr_nombre

Optimize GROUP_CONCAT in SQL on MySQL

Is there a way to get the following SQL optimized so it would run faster?
SELECT bitValue as bitV, endName as endN, filDuration as filD, filSize as filS, genName as genN, sonAdditionalPrefix AS sonAP, sonDate as sonD, sonID, sonIsRip, sonName, typName, sonPlays as plays,
(SELECT GROUP_CONCAT(a.artName SEPARATOR ';') FROM tblArtists a, tblSoAr sa WHERE a.artID = sa.soarartIDRef AND sa.soarsonIDRef = s.sonID) as artists,
(SELECT GROUP_CONCAT(a.artName SEPARATOR ';') FROM tblArtists a, tblRemixer r WHERE a.artID = r.remartIDRef AND r.remsonIDRef = s.sonID) as remixer,
(SELECT GROUP_CONCAT(a.artName SEPARATOR ';') FROM tblArtists a, tblFeaturing f WHERE a.artID = f.feaartIDRef AND f.feasonIDRef = s.sonID) as featuring,
(SELECT GROUP_CONCAT(ta.tagName SEPARATOR ';') FROM tblTags ta, tblSoTa st WHERE ta.tagID = st.sotatagIDRef AND st.sotasonIDRef = s.sonID) as tags
FROM tblSongs s, tblFiles f, tblGenres g, tblEndings e, tblBitrates b, tblTypes t
WHERE s.sonfilIDRef = f.filID AND s.songenIDRef = g.genID AND f.filendIDRef = e.endID AND f.filbitIDRef = b.bitID AND s.sontypIDRef = t.typID AND sonshaIDRef = 1 AND sonWasEdited = 1 AND sonDeleted = 0 AND sonOnWishlist = 0 ;
I encountered the bottleneck are the GROUP_CONCAT's but I couldn't find a way by using an alternative or optimizing the query so it would run faster.
At the moment the query needs about 3.2s on 2700 entries (mysql database 5.1.73, mysqli). All tables have indices set on the important columns.
So after implementing some LEFT JOINS my query looks the following:
SELECT bitValue as bitV, endName as endN, filDuration as filD, filSize as filS, genName as genN, sonAdditionalPrefix AS sonAP, sonDate as sonD, sonID, sonIsRip, sonName, typName, sonPlays as plays,
conArtists.artists, conRemixer.remixer, conFeaturing.featuring, conTags.tags
FROM (tblSongs s, tblFiles f, tblGenres g, tblEndings e, tblBitrates b, tblTypes t)
LEFT JOIN (SELECT tblSoAr.soarsonIDRef as soarsonIDRef, GROUP_CONCAT(tblArtists.artName SEPARATOR ';') as artists FROM tblSoAr, tblArtists WHERE tblArtists.artID = tblSoAr.soarartIDRef GROUP BY soarsonIDRef) AS conArtists ON conArtists.soarsonIDRef = s.sonID
LEFT JOIN (SELECT tblRemixer.remsonIDRef as remsonIDRef, GROUP_CONCAT(tblArtists.artName SEPARATOR ';') as remixer FROM tblRemixer, tblArtists WHERE tblArtists.artID = tblRemixer.remsonIDRef GROUP BY remsonIDRef) AS conRemixer ON conRemixer.remsonIDRef = s.sonID
LEFT JOIN (SELECT tblFeaturing.feasonIDRef as feasonIDRef, GROUP_CONCAT(tblArtists.artName SEPARATOR ';') as featuring FROM tblFeaturing, tblArtists WHERE tblArtists.artID = tblFeaturing.feasonIDRef GROUP BY feasonIDRef) AS conFeaturing ON conFeaturing.feasonIDRef = s.sonID
LEFT JOIN (SELECT tblSoTa.sotasonIDRef as sotasonIDRef, GROUP_CONCAT(tblTags.tagName SEPARATOR ';') as tags FROM tblSoTa, tblTags WHERE tblTags.tagID = tblSoTa.sotasonIDRef GROUP BY sotasonIDRef) AS conTags ON conTags.sotasonIDRef = s.sonID
WHERE s.sonfilIDRef = f.filID AND s.songenIDRef = g.genID AND f.filendIDRef = e.endID AND f.filbitIDRef = b.bitID AND s.sontypIDRef = t.typID AND sonshaIDRef = 1 AND sonWasEdited = 1 AND sonDeleted = 0 AND sonOnWishlist = 0;
I think you can avoid the subqueries (that are done for every row) by grouping the artName values first and then joining them:
old query:
select
a.id,
(select group_concat(x) as x_concat from table_2 as _b where a.id = _b.id and ...) as b,
(select group_concat(x) as x_concat from table_3 as _c where a.id = _b.id and ...) as c
from table_1 as a
where ...
Should be something like this:
select
a.id,
b.x_concat,
c.x_concat
from
table_1 as a,
left join (select id, group_concat(x) as x_concat from table_2 where ... group by id) as b on a.id = b.id,
left join (select id, group_concat(x) as x_concat from table_3 where ... group by id) as c on a.id = c.id
where ...

how to GROUP_CONCAT with Concat

Product name supplier
A Su1
A Su1
A Su2
B Su1
C Su3
I want like this
A - su1, A-su2, B-su1, C-su3
Query:
SELECT
vtiger_salesorder.salesorder_no,
(Select
group_concat(DISTINCT concat(vtiger_products.productname, '-', vtiger_vendor.vendorname ) SEPARATOR ', ')
FROM
vtiger_salesorder
LEFT Join vtiger_inventoryproductrel ON vtiger_salesorder.salesorderid = vtiger_inventoryproductrel.id
inner Join vtiger_products ON vtiger_products.productid = vtiger_inventoryproductrel.productid
inner Join softMax_SalesOrderVendorInfo ON softMax_SalesOrderVendorInfo.salesorderid = vtiger_salesorder.salesorderid
LEFT JOIN vtiger_vendor ON softMax_SalesOrderVendorInfo.vendorid = vtiger_vendor.vendorid
where (vtiger_salesorder.salesorderid = vtiger_inventoryproductrel.id
AND vtiger_salesorder.salesorderid = vtiger_crmentity.crmid
and (softMax_SalesOrderVendorInfo.status = '0') )Group by vtiger_salesorder.salesorderid Limit 0,1) As SuName1
FROM
vtiger_salesorder
INNER JOIN vtiger_inventoryproductrel ON vtiger_salesorder.salesorderid = vtiger_inventoryproductrel.id
Inner Join vtiger_crmentity ON vtiger_salesorder.salesorderid = vtiger_crmentity.crmid
Order by vtiger_salesorder.salesorder_no
Given your original data, you can simply do this with something like:
select distinct group_concat(ProductName, '-', Supplier separator ', ')
from table t;
I have no idea what the query has to do with the question, because you already seem to have the data in the appropriate format.