Left join with multiple tables and conditions - mysql

I want to sort after a value in another table the current table is referenced to. My query looks like this:
SELECT o._id,
o.titel,
o.beschreibung
FROM `objekt` AS o,
`objekt_einzel` AS oe,
`objekt_einzel_immobilie` AS oei,
`objekt_art` AS oa,
`verortung` AS v
#here
,`person` AS p,
`person_bauträger` AS pb
#end
WHERE o._id = oe.objekt_id
AND oe._id = oei.objekt_einzel_id
AND oa._id = o.objekt_art_id
AND o.ort_id = v._id
#here
AND oe.bauträger_id = pb._id
AND pb.person_id = p._id
#end
AND ( oei.justimmo_objekt_id = "0"
OR oei.justimmo_objekt_id IS NULL
OR oei.justimmo_objekt_id = "" )
#here
ORDER BY p.firmenbezeichnung ASC
The query is working fine but it shows me only values if oe.bauträger_id is set. I also want the null values. So I need a left join. I tried different things but I only get messages like unknown column or I get too much results.
I tried to simplify it to this:
SELECT o._id,
o.titel,
o.beschreibung
FROM `objekt` AS o,
`objekt_einzel` AS oe,
(SELECT oe.bauträger_id
FROM objekt o, objekt_einzel oe, objekt_einzel_immobilie oei
WHERE o._id = oe.objekt_id AND oe._id = oei.objekt_einzel_id) AS menge1
LEFT JOIN
(SELECT pb._id AS bauträger_id
FROM person p, person_bauträger pb
WHERE p._id = pb.person_id) AS menge2
ON menge1.bauträger_id = menge2.bauträger_id
WHERE o._id = oe.objekt_id AND oe.bauträger_id = menge1.bauträger_id
but here I get a too big result set. I don't know how to explain this better. The data sets are too big to create an example. I hope you understand what I mean.

SELECT o._id,
o.titel,
o.beschreibung
FROM `objekt` AS o
JOIN `objekt_einzel` AS oe ON o._id = oe.objekt_id
JOIN `objekt_einzel_immobilie` AS oei ON oe._id = oei.objekt_einzel_id
JOIN `objekt_art` AS oa ON o.objekt_art_id = oa._id
JOIN `verortung` AS v ON o.ort_id = v._id
LEFT JOIN `person_bauträger` AS pb ON oe.bauträger_id = pb._id
LEFT JOIN `person` AS p ON pb.person_id = p._id
WHERE oei.justimmo_objekt_id = "0"
OR oei.justimmo_objekt_id IS NULL
OR oei.justimmo_objekt_id = ""
ORDER BY p.firmenbezeichnung ASC
This second try should work as it is just the original code rewritten using JOIN syntax and with LEFT JOINs.

Related

How to speed up loading data from MySQL query with multiple joins

When I run this query it only displays loading that is not finished. So the time to run the query has run out without displaying any data. In fact, making computer operations become very slow.
Here is the problem. I am selecting and doing multiple joins to get the correct items... This query takes so long time. Anyone know how I can speed this up? Here is the query.
SELECT a.*,
LEFT(a.tgl_inovasi, 10) AS tgl_ino, b.`nm_unit`, c.`nm_inovasijns`,
d.`nm_regulasi`, e.`nm_sediasdm`, f.`nm_anggaran`, g.`nm_it`, h.`nm_bimtek`,
i.`nm_renstra`, j.`nm_jejaring`, k.`nm_replikasi`, l.`nm_pedoman`,
m.`nm_pengelola`, n.`nm_informasi`, o.`nm_penyelesaian`, p.`nm_partisipasi`,
q.`nm_kemudahaninf`, r.`nm_kemudahanpro`, s.`nm_online`, t.`nm_kecepatan`,
u.`nm_kemanfaatan`, v.`nm_kepuasan`, w.`nm_user`, x.nm_inovasikat
FROM inovasi a, unit b, inovasijns c, regulasi d, sediasdm e, anggaran f,
it g, bimtek h, renstra i, jejaring j, replikasi k, pedoman l, pengelola m,
informasi n, penyelesaian o, partisipasi p, kemudahaninf q, kemudahanpro r,
online s, kecepatan t, kemanfaatan u, kepuasan v, `user` w, inovasikat x
WHERE x.id_inovasikat = a.id_inovasikat AND w.`id_user` = a.`id_user` AND
v.`id_kepuasan` = a.`id_kepuasan` AND u.`id_kemanfaatan` = a.`id_kemanfaatan` AND
t.`id_kecepatan` = a.`id_kecepatan` AND s.`id_online` = a.`id_online` AND
r.`id_kemudahanpro` = a.`id_kemudahanpro` AND q.`id_kemudahaninf` =
a.`id_kemudahaninf` AND p.`id_partisipasi` = a.`id_partisipasi` AND
o.`id_penyelesaian` = a.`id_penyelesaian` AND n.`id_informasi` = a.`id_informasi`
AND m.`id_pengelola` = a.`id_pengelola` AND l.`id_pedoman` = a.`id_pedoman` AND
k.`id_replikasi` = a.`id_replikasi` AND j.`id_jejaring` = a.`id_jejaring` AND
i.`id_renstra` = a.`id_renstra` AND h.`id_bimtek` = a.`id_bimtek` AND g.`id_it` =
a.`id_it` AND f.`id_anggaran` = a.`id_anggaran` AND e.`id_sediasdm` =
a.`id_sediasdm` AND d.`id_regulasi` = a.`id_regulasi` AND c.`id_inovasijns` =
a.`id_inovasijns` AND b.`id_unit` = a.`id_unit` AND a.no_inovasi = '$no_inovasi'
I try looking for the solution from other threat, almost all of them suggest using an index. But I don't understand which tables and fields should be added to the index. Please help to solve this problem.
I already run this query :
CREATE INDEX idx_inovasi1 ON inovasi (no_inovasi, tgl_inovasi, satuan, id_unit, nm_kelompok, subjek, id_inovasijns, id_inovasikat, id_regulasi, regulasi_doc, id_sediasdm, sediasdm_doc);
but it still hasn't affected anything.
How about switching to left join's, using the modern JOIN syntax.
SELECT a.*
, LEFT(a.tgl_inovasi, 10) AS tgl_ino
, b.`nm_unit`
, c.`nm_inovasijns`
, d.`nm_regulasi`
, e.`nm_sediasdm`
, f.`nm_anggaran`
, g.`nm_it`
, h.`nm_bimtek`
, i.`nm_renstra`
, j.`nm_jejaring`
, k.`nm_replikasi`
, l.`nm_pedoman`
, m.`nm_pengelola`
, n.`nm_informasi`
, o.`nm_penyelesaian`
, p.`nm_partisipasi`
, q.`nm_kemudahaninf`
, r.`nm_kemudahanpro`
, s.`nm_online`
, t.`nm_kecepatan`
, u.`nm_kemanfaatan`
, v.`nm_kepuasan`
, w.`nm_user`
, x.nm_inovasikat
FROM inovasi a
LEFT JOIN unit b ON b.`id_unit` = a.`id_unit`
LEFT JOIN inovasijns c ON c.`id_inovasijns` = a.`id_inovasijns`
LEFT JOIN regulasi d ON d.`id_regulasi` = a.`id_regulasi`
LEFT JOIN sediasdm e ON e.`id_sediasdm` = a.`id_sediasdm`
LEFT JOIN anggaran f ON f.`id_anggaran` = a.`id_anggaran`
LEFT JOIN it g ON g.`id_it` = a.`id_it`
LEFT JOIN bimtek h ON h.`id_bimtek` = a.`id_bimtek`
LEFT JOIN renstra i ON i.`id_renstra` = a.`id_renstra`
LEFT JOIN jejaring j ON j.`id_jejaring` = a.`id_jejaring`
LEFT JOIN replikasi k ON k.`id_replikasi` = a.`id_replikasi`
LEFT JOIN pedoman l ON l.`id_pedoman` = a.`id_pedoman`
LEFT JOIN pengelola m ON m.`id_pengelola` = a.`id_pengelola`
LEFT JOIN informasi n ON n.`id_informasi` = a.`id_informasi`
LEFT JOIN penyelesaian o ON o.`id_penyelesaian` = a.`id_penyelesaian`
LEFT JOIN partisipasi p ON p.`id_partisipasi` = a.`id_partisipasi`
LEFT JOIN kemudahaninf q ON q.`id_kemudahaninf` = a.`id_kemudahaninf`
LEFT JOIN kemudahanpro r ON r.`id_kemudahanpro` = a.`id_kemudahanpro`
LEFT JOIN online s ON s.`id_online` = a.`id_online`
LEFT JOIN kecepatan t ON t.`id_kecepatan` = a.`id_kecepatan`
LEFT JOIN kemanfaatan u ON u.`id_kemanfaatan` = a.`id_kemanfaatan`
LEFT JOIN kepuasan v ON v.`id_kepuasan` = a.`id_kepuasan`
LEFT JOIN `user` w ON w.`id_user` = a.`id_user`
LEFT JOIN inovasikat x ON x.id_inovasikat = a.id_inovasikat
WHERE a.no_inovasi = '$no_inovasi'
As for the indexes. There's almost a whole alphabeth of tables linked.
Most are probably joined on the primary index.
So look at the defenition of those tables, and discover which tables don't have their PK joined.
Maybe those could benefit from an index on the field used in the query.
you should use indexes, check how to index fields, but above all index the fields you have after the "where"
If you add the results of the EXPLAIN (your SQL), it would be helpful to pinpoint issues.
https://dev.mysql.com/doc/refman/8.0/en/explain.html

How to access outer table data in join where

How can I access data from an outer table in a SELECT, and use it in an WHERE inside a JOIN estructure?
Below is the current query:
SELECT
cvl.id caracteristica_valor_id,
cvl.nome caracteristica_valor_nome,
cvl.valor caracteristica_valor_valor,
ctp.id caracteristica_tipo_id,
ctp.nome caracteristica_tipo_nome,
ctp.codigo caracteristica_tipo_codigo,
ctp.tipo caracteristica_tipo_tipo,
COUNT(DISTINCT var.id_perfil_produto) quantidade_itens
FROM
caracteristica_variacao cvr
INNER JOIN caracteristica_valor cvl ON cvl.id = cvr.id_caracteristica_valor
INNER JOIN caracteristica_tipo ctp ON ctp.id = cvl.id_caracteristica_tipo
INNER JOIN variacao var ON var.id = cvr.id_variacao
INNER JOIN(
SELECT DISTINCT
ppr.id perfil_produto_id
FROM
perfil_produto ppr
INNER JOIN produto pro ON pro.id = ppr.id_produto
INNER JOIN(
SELECT ppr2.id AS id_perfil_sub,a
COUNT(var.id) AS qtd_variacoes,
SUM(var.quantidade_estoque) AS quantidade_estoque,
COALESCE(SUM(var.quantidade_estoque_reservada),0) AS quantidade_estoque_reservada,
MIN(var.disponibilidade) AS disponibilidade,
MIN(var.frete_gratis) AS frete_gratis,
MIN(var.preco_venda) AS preco_venda,
MAX(var.preco_listagem) AS preco_listagem
FROM
variacao var
LEFT JOIN perfil_produto ppr2 ON ppr2.id = var.id_perfil_produto
LEFT JOIN caracteristica_variacao cvr_1 ON cvr_1.id_variacao = var.id
LEFT JOIN caracteristica_valor cvl_1 ON cvl_1.id = cvr_1.id_caracteristica_valor
LEFT JOIN caracteristica_tipo ctp_1 ON ctp_1.id = cvl_1.id_caracteristica_tipo
WHERE
var.disponibilidade = 1
AND(
ctp_1.codigo = 'tamanho' AND cvl_1.valor IN('p')
)
GROUP BY
ppr2.id
) AS grp_var ON grp_var.id_perfil_sub = ppr.id
INNER JOIN produto_categoria prc ON pro.id = prc.produto_id
INNER JOIN categoria cat ON prc.categoria_id = cat.id
WHERE
pro.disponibilidade = 1 AND prc.categoria_id IN (164, 165, 166)
) AS produto ON produto.perfil_produto_id = var.id_perfil_produto
GROUP BY
cvl.id
ORDER BY
ctp.tipo ASC,
ctp.id
I need the field ctp.codigo from the outer table inside thist part:
WHERE
var.disponibilidade = 1
AND(
ctp_1.codigo = 'tamanho' AND cvl_1.valor IN('p')
)
for this section to be as follows:
WHERE
var.disponibilidade = 1
AND(
(ctp.codigo != 'tamanho' AND ctp_1.codigo = 'tamanho' AND cvl_1.valor IN('p'))
OR
(ctp.codigo = 'tamanho')
)
It's not possible to reference columns from the outer query from inside an inline view query.
In the MySQL venacular, the inline view query is called a "derived table". And that name makes sense, because of the way MySQL processes it. The execution plan first materializes the inline view query into a temporary(-ish) table. Once that is done, then the outer query can run, referencing the contents of the derived table.
MySQL doesn't have available the columns from the outer query at the time the inline view query runs.
It is possible to reference columns from the outer query inside a subquery that appears for example in the SELECT list, or in the WHERE clause. We call a subquery that references columns from outer query a "correlated subquery".

How to join a few tables without repeat?

I have a SQL query that left joins a few tables in different ways depending on a conditions.
SELECT
dh_partner.company_name,
dh_partner_abonnement.name,
dh_partner_abonnement.description,
dh_partner_abonnement.price,
dh_partner_abonnement.discount_price,
dh_studio.partner_id,
CONCAT('https://some.url/images/studio/logo/', dh_studio.logo) as logo_url,
CONCAT('https://some.url/studio/', dh_studio.alias) as page_url,
CONCAT('https://some.url/order/abonnement/', dh_studio.alias, '/', dh_partner_abonnement_studios.abonnement_id) as checkout_url
FROM dh_partner_abonnement
LEFT JOIN dh_partner on dh_partner.id = dh_partner_abonnement.partner_id
LEFT JOIN dh_studio on dh_studio.partner_id = dh_partner.id
LEFT JOIN dh_partner_abonnement_studios on dh_partner_abonnement_studios.studio_id = dh_studio.id
WHERE
dh_partner.status = 'active'
and dh_partner.id = dh_studio.partner_id
and dh_partner.city_id = '1'
and dh_partner_abonnement_studios.studio_id = dh_studio.id
and dh_studio.show_status = '1'
The challenge in the following code
CONCAT('https://some.url/ru/order/abonnement/', dh_studio.alias, '/', dh_partner_abonnement_studios.abonnement_id) as checkout_url
LEFT JOIN dh_partner_abonnement_studios on dh_partner_abonnement_studios.studio_id = dh_studio.id
and dh_partner_abonnement_studios.studio_id = dh_studio.id
It repeats to the each dh_partner_abonnement this column dh_partner_abonnement_studios.abonnement_id
I have to connect them correctly. I know that I need to use if, however having no idea how.
Just guessing from the table names:
SELECT
p.company_name,
pa.name,
pa.description,
pa.price,
pa.discount_price,
s.partner_id,
CONCAT('https://some.url/images/studio/logo/', s.logo) as logo_url,
CONCAT('https://some.url/studio/', s.alias) as page_url,
CONCAT('https://some.url/order/abonnement/', s.alias, '/', pa.abonnement_id)
as checkout_url
FROM dh_partner_abonnement pa
JOIN dh_partner_abonnement_studios pas ON pas.partner_id = pa.partner_id
AND pas.abonnement_id = pa.abonnement_id
JOIN dh_studio s ON s.id = pas.studio_id
AND s.show_status = 1
JOIN dh_partner p ON p.id = pa.partner_id
AND p.status = 'active'
AND p.city_id = 1
You haven't joined dh_partner_abonnement and dh_partner_abonnement_studios on the complete key, which should include the abonnement_id.
It also seems a studio has a partner_id to indicate that it belongs to a certain partner. However, in your query you are interested in the abbonement studios, so join the studio on the abbonement's studio_ids.

Use Multiple Varchar as a parameter

I am trying to create a query that will allow me to use multiple VarChars as a parameter in SSRS.
Here's the code:
Declare #CallCodes as VarChar(10)
Set #CallCodes = ('MORC30' , 'Morc60')
;
With Data
AS
(SELECT
VC.[CallCode]
,VC.[HospCode]
,VC.[HospMastID]
,VC.[ClientID]
,Row_Number () Over (Partition By HospMastID, VC.ClientID Order By HospMastID, VC.ClientID, GLCode) as Txn
FROM
[RptSys].[dbo].[CSC_VuesionImport_DevDetl] as VC
Inner Join
[AVimark_OLTP].[dbo].[Client] as C
on
VC.HospMastID = C.HospitalMasterID
and
VC.ClientID = C.ClientID
Inner Join
[Avimark_OLTP].[dbo].[Patient] as P
on
VC.HospMastID = P.HospitalMasterID
and
VC.PatientID = P.PatientID
Inner Join
[Avimark_OLTP].[dbo].[Treatment] as T
on
VC.HospMastID = T.HospitalMasterID
and
VC.MastReminder = T.Code
Where
VC.CallCode in #CallCodes)
This gives an error when I try to run it. The final output is to allow the end user to choose from a drop down list in an SSRS report I have tried all variations of in or like for the where statement.
Any suggestions would be greatly appreciated.
Why don't you take the Parmaeter in a temporary table marked with #
CREATE TABLE #tmp(
Callcodes varchar(10))
INSERT INTO #tmp
VALUES
('MORC30'),
('Morc60')
With Data
AS
(SELECT
VC.[CallCode]
,VC.[HospCode]
,VC.[HospMastID]
,VC.[ClientID]
,Row_Number () Over (Partition By HospMastID, VC.ClientID Order By HospMastID, VC.ClientID, GLCode) as Txn
FROM
[RptSys].[dbo].[CSC_VuesionImport_DevDetl] as VC
Inner Join
[AVimark_OLTP].[dbo].[Client] as C
on
VC.HospMastID = C.HospitalMasterID
and
VC.ClientID = C.ClientID
Inner Join
[Avimark_OLTP].[dbo].[Patient] as P
on
VC.HospMastID = P.HospitalMasterID
and
VC.PatientID = P.PatientID
Inner Join
[Avimark_OLTP].[dbo].[Treatment] as T
on
VC.HospMastID = T.HospitalMasterID
and
VC.MastReminder = T.Code
Where
VC.CallCode in (SELECT * FROM #tmp))
I hope this is what you are looking for, if not please tell me. Or like mentioned in the comments give a error message
Have a nice day & greets from Switzerland
Etienne

Need help updating table from a select query

I have the following code that produces a list of order numbers and values...
SELECT
d.`OrderNo`,
SUM(v.`UnitPrice`)
FROM tblverification v
LEFT JOIN tblorderdetailsafter d ON v.`VMainID` = d.`MainID`
GROUP BY d.`OrderNo`;
I need to update a table called matcontctsafter which has an OrderNo field and currently blank InvoiceAmount column that I need the relative SUM(v.UnitPrice) in.
Can anybody help me construct the UPDATE clause?
UPDATE matcontctsafter m
INNER JOIN (
SELECT
d.`OrderNo`,
SUM(v.`UnitPrice`) InvoiceAmount
FROM tblverification v
LEFT JOIN tblorderdetailsafter d ON v.`VMainID` = d.`MainID`
GROUP BY d.`OrderNo`
) sq ON m.OrderNo = sq.OrderNo
SET m.InvoiceAmount = sq.InvoiceAmount;
UPDATE matcontctsafter m SET m.InvoiceAmount = (SELECT
SUM(v.UnitPrice)
FROM tblverification v
LEFT JOIN tblorderdetailsafter d ON v.VMainID = d.MainID
WHERE m.OrderNo = d.OrderNo);