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.
Related
I have the query, which is giving correct result, but, I am sure there are other way to do so, having same conditions repeated.
Can anybody help me to reduce the complexity of the query.
Query using these mysql parameters:-
SELECT avai.account_visit_account_info_pk AS Account_ID,
mb.NAME AS Client_Name,
mb.fullname AS Client_Full_Name,
avai.account_name AS Account_Name,
mc.NAME AS Asset_City,
Format(( bfd.finance_value ), 'en_IN') AS Reserve_Price,
Format(( bfd.finance_value ) * 10 / 100, 'en_IN') AS EMD_Value,
Ifnull(Concat(CASE
WHEN mpc.parent = 4 THEN 'Residential'
WHEN mpc.parent = 5 THEN 'Commercial'
WHEN mpc.parent = 6 THEN 'Industrial'
WHEN mpc.parent = 7 THEN 'Agricultural'
END, '/', mpc.category_name), mpc.category_name) Asset_Category,
Concat(ud.first_name, ' ', ud.last_name) AS ADM_Name,
Concat(udd.first_name, ' ', udd.last_name) AS MKT_Name,
mcc.NAME AS ADM_City,
ms.NAME AS ADM_State,
mz.NAME AS ADM_Zone,
bec.e_auction_from AS Auction_Date,
bfdd.finance_value AS Sold_Price
FROM account_branch_visit abv
JOIN mst_product_category mpc
ON mpc.mst_product_category_pk = abv.mst_product_category_pk
JOIN mst_bank mb
ON abv.mst_bank_pk = mb.mst_bank_pk
JOIN banking_financial_details bfd
ON abv.account_branch_visit_pk = bfd.account_branch_visit_pk
AND bfd.mst_financial_pk IN ( 33 )
LEFT JOIN banking_financial_details bfdd
ON abv.account_branch_visit_pk = bfdd.account_branch_visit_pk
AND bfd.mst_financial_pk IN ( 38 )
JOIN mst_city mc
ON mc.mst_city_pk = avai.mst_city_pk
JOIN mst_city mcc
ON mcc.mst_city_pk = avai.mst_city_pk
JOIN mst_state ms
ON ms.mst_state_pk = mcc.mst_state_pk
JOIN mst_zone mz
ON mz.mst_zone_pk = ms.mst_zone_pk
JOIN case_allocation ca
ON ca.account_branch_visit_pk = avai.account_branch_visit_pk
AND ca.mst_activity_pk = 21
JOIN case_allocation caa
ON caa.account_branch_visit_pk = avai.account_branch_visit_pk
AND caa.mst_activity_pk = 18
JOIN user_detail ud
ON ud.user_detail_pk = ca.assignedto
JOIN user_detail udd
ON udd.user_detail_pk = caa.assignedto
JOIN banking_event_calender bec
ON bec.account_branch_visit_pk = avai.account_branch_visit_pk
AND ( abv.closed_reasons_pk IS NULL
OR abv.closed_reasons_pk = 16 )
AND abv.isdeleted = '0'
WHERE avai.account_branch_visit_pk = '1301';
I do not know what the exact intent of the query is, so I will provide some technical nuances, without actually understanding your data model or goal. The select clause provides you some columns and you probably need it. So, what I'm looking for are duplicate table joins. Some of them are necessary, some of them are unnecessary.
banking_financial_details
You join and left join this table with different ideas. You use both of them, so I assume this is necessary.
mst_city
This is obviously unnecessarily duplicating:
JOIN mst_city mc
ON mc.mst_city_pk = avai.mst_city_pk
JOIN mst_city mcc
ON mcc.mst_city_pk = avai.mst_city_pk
Remove the second JOIN and ON clauses from the above and replace all usages of mcc to mc in the query.
case_allocation
You join this table twice, but with different ids and you then join the corresponding user_detail to both and both user_detail instances are being used, so this is probably necessary.
user_detail
Since this duplicated join seems to be used in the select, it's probably necessary.
Summary
We have found an unnecessary join that can be removed. Further shortening of the query may be possible, but we would need to know more about your task and database to determine further improvements.
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".
I am not so into database and I have the following doubt. I am using MySql
I have this query that return multiple records (it works fine) and I have to add the WHERE clause in such a way that some fields are mandatory and some other fields are optional.
So I have this query:
SELECT
EnutrifoodMessage.content
, MessageType.message_type_name
, Country.country_name
, IFNULL(Province.province_name, 'All Provinces') as province_name
, IFNULL(District.district_name, 'Any District') as district_name
, Crop.crop_name
, EnutriMessageDetails.creation_date
, EnutriMessageDetails.message_important_days
, temp_scale.scale_name as temperature
, humidity_scale.scale_name as humidity
, ProcessPhase.phase_name
, ProcessPhaseAction.process_phase_action_name
, Urgency.urgency_name as action
, IFNULL(MeteoWarningDescription.meteo_warning_description_name, '') as emergency
, IFNULL(EnutriMessageDetails.internal_link, '') as internal_link
, IFNULL(EnutriMessageDetails.reference_link, '') as reference_link
, IFNULL(EnutriMessageDetails.external_link, '') as external_link
, IFNULL(cleared_by_institution.institution_name, '') as message_cleared_by
, UserType.user_type_name as end_user
, provider.institution_name as provider
, ValueAddition.value_addition_name
FROM EnutriMessageDetails
LEFT JOIN EnutrifoodMessage
ON EnutrifoodMessage.id = EnutriMessageDetails.enutri_food_message_id
LEFT JOIN MessageType
ON MessageType.id = EnutriMessageDetails.message_type_id
LEFT JOIN Localization
ON Localization.id = EnutriMessageDetails.localization_id
LEFT JOIN Country
ON Country.id = Localization.country_id
LEFT JOIN Province
ON Province.id = Localization.province_id
LEFT JOIN District
ON District.id = Localization.district_id
LEFT JOIN Crop
ON Crop.id = EnutriMessageDetails.crop_id
LEFT JOIN Scale temp_scale
ON temp_scale.id = EnutriMessageDetails.temp_scale_id
LEFT JOIN Scale humidity_scale
ON humidity_scale.id = EnutriMessageDetails.humidity_scale_id
LEFT JOIN ProcessPhase
ON ProcessPhase.id = EnutriMessageDetails.process_phase_id
LEFT JOIN ProcessPhaseAction
ON ProcessPhaseAction.id = EnutriMessageDetails.process_phase_action_id
LEFT JOIN Urgency
ON Urgency.id = EnutriMessageDetails.urgency_id
LEFT JOIN MeteoWarningDescription
ON MeteoWarningDescription.id = EnutriMessageDetails.meteo_warning_description_id
LEFT JOIN Institution cleared_by_institution
ON cleared_by_institution.id = EnutriMessageDetails.cleared_by_id
LEFT JOIN UserType
ON UserType.id = EnutriMessageDetails.user_type_id
LEFT JOIN Institution provider
ON provider.id = EnutriMessageDetails.provided_by_id
LEFT JOIN ValueAddition
ON ValueAddition.id = EnutriMessageDetails.value_addition_id
WHERE Localization.id = 2
AND Crop.id = 2
ORDER BY EnutrifoodMessage.id
I need to add the WHERE clause in such a way that:
1) This field is mandatory:
Localization.id = 2
UserType.id = 1
2) These other fields are optional:
EnutriMessageDetails.creation_date >= a specified date
Urgency.id = 3
I want that the first type of field have to be inserted, the other type have to be optional and can be not fill.
How can I correctly handle this situation?
Try case expression:
Where Localization.id = 2 and UserType.id = 1 and
1 = case when EnutriMessageDetails.creation_date >= **[a specified date]**
then case when and Urgency.id = 3
then 1
else 0
end
else 1
end
Edit: Correction.
Please try the following to test if it will work this is to check if its null or not. So then you can react on it.
WHERE Urgency.id LIKE CASE WHEN Urgency.id IS NULL
THEN Urgency.id
ELSE CONCAT('%', Urgency.id, '%')
END
I dont have a testing environment for mySql so please check if it will work just trying to help.
It seems you want:
WHERE (urgency.id = #urgencyid OR #urgencyid IS NULL)
or
ON (urgency.id = #urgencyid OR #urgencyid IS NULL)
So when an ID is given, only data matching the ID will be selected, and if no ID is given, all data will.
The WHERE clause will not select any record if the ID does not exist in the table. So the urgency table should be inner-joined. If it is outer-joined, the WHERE clause turns it into an inner join, as records with ID null will be dismissed. Avoid such pseudo outer joins.
For an inner join it doesn not matter whether to use WHERE or ON. For an outer join, however, the WHERE clause would turn it into an inner join as mentioned, whereas the ON clause would still outer-join (with a given ID, either the ID is found or an empty dummy record joined).
My code below works, but I am getting more than 1 record per Item_TAG which I dont want to. I tried changing ESP_Facturacao.[1a_mesAno] as Data, to MAX(ESP_Facturacao.[1a_mesAno]) as Data;
It did not work. Anyone has a suggestion?
SELECT
ESP_Fisico.ESP_SubTipo_ID,
ESP_Fisico.ESP_Unidade_ID,
ESP_Facturacao.Item_TAG,
ESP_Facturacao.[1a_MesAno] AS Data,
ESP_Facturacao.[1a_Faturado] AS Valor,
'1 a' AS Tarefa,
'1' AS Control,
'1' AS Estado,
ESP_SubTipo.Descrição AS SubTipo,
ESP_Unidade.Descricao AS Unidade,
ESP_Facturacao.ID
FROM ESP_Unidade INNER JOIN (((ESP_TAG LEFT JOIN ESP_Facturacao ON ESP_TAG.ID = ESP_Facturacao.ESP_Tag_ID) INNER JOIN (ESP_SubTipo INNER JOIN ESP_Fisico ON ESP_SubTipo.ID = ESP_Fisico.ESP_SubTipo_ID) ON ESP_TAG.ID = ESP_Fisico.ESP_Tag_ID) INNER JOIN ESP_Administrativas ON ESP_TAG.ID = ESP_Administrativas.ESP_Tag_ID) ON ESP_Unidade.ID = ESP_Fisico.ESP_Unidade_ID
WHERE (((ESP_Facturacao.Item_TAG) Not In (SELECT ESP_Facturacao.Item_TAG
FROM ESP_Facturacao
WHERE (((ESP_Facturacao.[1a_MesAno]) Is Not Null)))) AND ((ESP_Administrativas.Data_Aut_Funcion) Is Null) AND ((ESP_Administrativas.Novo_Pos_2010)=True));
I am getting this error message, can someone advise on a solution?
I have looked over this forum and cant find a solution
Dynamic SQL Error
SQL error code = -104
Invalid command
no column name specified for column number 1 in derived table ACCRG
SELECT DISTINCT locationgroup.name AS MainGroup, product.num AS ProductNumber,
product.description AS ProductDescription, uom.code AS UOM, company.name AS company,
sum(((SELECT SUM(productsSold.qtyfulfilled) FROM soitem productsSold WHERE soitem.id = productsSold.id AND productsSold.productid = product.id) * COALESCE(uomconversion.multiply,1)) / COALESCE(uomconversion.factor,1)) AS uomqty
FROM soitem
LEFT OUTER JOIN so ON (so.id = soitem.soid)
LEFT OUTER JOIN product ON (soitem.productid = product.id)
LEFT OUTER JOIN uom ON (product.uomid = uom.id)
LEFT OUTER JOIN locationgroup ON (so.locationgroupid = locationgroup.id)
LEFT OUTER JOIN qbclass ON (qbclass.id = soitem.qbclassid)
LEFT OUTER JOIN customer ON (customer.id = so.customerid)
LEFT JOIN (SELECT max(accountgrouprelation.id) AS relationID, accountgrouprelation.accountid
FROM accountgrouprelation
LEFT JOIN accountGroup ON accountGroupRelation.groupId = accountGroup.id
WHERE UPPER(COALESCE (accountgroup.name, '%')) LIKE UPPER('%')
GROUP BY 2) accrg ON customer.accountid = accrg.accountid
LEFT JOIN accountgrouprelation ON accrg.relationid = accountgrouprelation.id
LEFT OUTER JOIN accountgroup ON (accountgroup.id = accountgrouprelation.groupid)
LEFT OUTER JOIN uomconversion ON ((product.uomid = uomconversion.touomid) AND (soitem.uomid = uomconversion.fromuomid))
JOIN company ON company.id = 1
WHERE soitem.qtyfulfilled > 0
AND soitem.typeid in (10,12,80)
AND locationgroup.id IN (1,2,3,4)
AND qbclass.id LIKE '%'
AND UPPER(so.salesman) LIKE UPPER('%')
AND UPPER(COALESCE (accountgroup.name, '%')) LIKE UPPER('%')
AND soitem.datelastfulfillment BETWEEN '2015-11-30 23:59:59.0' AND '2015-12-31 23:59:59.0'
GROUP BY maingroup, productnumber, productdescription, uom, company
ORDER BY 1,product.num ASCENDING
Believe it or not, I think the error is coming from your ORDER BY statement:
ORDER BY 1,product.num ASCENDING
I don't believe it is legal to ORDER BY a constant number in MySQL. Telling by the error, it appears that MySQL is trying to find a column called 1 in the ACCRG derived table. No such column exists, hence you are getting this error. Instead, why not just ORDER BY the product number?:
ORDER BY product.num ASCENDING