I am trying to write a query that uses a LEFT OUTER JOIN on three tables. I have complete the first part to join two tables but I am stuck on intergarting the third table.
What I need is the "Status" field for the NXLHR_Valid to be included in the first query.
Below are my to queries, how would I include the SECOND query into the FIRST query
FIRST QUERY
SELECT NXLHR_SequenceNo_default.SeqNo, NXLHR_SequenceNo_default.SeqHeader, NXLHR_SequenceNo_default.SeqText, NXLHR_Hist.UniqueID, NXLHR_Hist.Room, NXLHR_Hist.Status, NXLHR_Hist.Water, NXLHR_Hist.AuditBy
FROM NXLHR_SequenceNo_default
LEFT OUTER JOIN NXLHR_Hist
ON NXLHR_SequenceNo_default.SeqID = NXLHR_Hist.SeqID
AND NXLHR_Hist.UniqueID = 'NXLHR01031472477564'
WHERE NXLHR_SequenceNo_default.SeqActive = 1
ORDER BY NXLHR_SequenceNo_default.OrderID
SECOND QUERY
SELECT NXLHR_Valid.UniqueID, NXLHR_Valid.Status
FROM NXLHR_Valid
WHERE NXLHR_Valid.UniqueID = 'NXLHR01031472477564'
Any help would be great. Thank you for your time.
SELECT d.SeqNo
, d.SeqHeader
, d.SeqText
, h.UniqueID
, h.Room
, h.Status
, h.Water
, h.AuditBy
, v.Status
FROM NXLHR_SequenceNo_default d
LEFT
JOIN NXLHR_Hist h
ON h.SeqID = d.SeqID
AND h.UniqueID = 'NXLHR01031472477564'
LEFT
JOIN NXLHR_Valid v
ON v.UniqueID = h.UniqueID
WHERE d.SeqActive = 1
ORDER
BY d.OrderID
Related
Using Report Builder 3.0, I have a report using the following dataset:
Declare #Hierarchy nVarChar (1000) = EAC.GetHierarchy (#UserName, DEFAULT)
SELECT TOP(100)
CASE
WHEN #ShowSourceTime = 1 THEN SourceTime
ELSE Dateadd(Minute, #TimeZoneOffset, Time)
END as Time
,Warehouse.EventInfo.TimeZoneShortName
,Warehouse.EventInfo.Category
,Warehouse.EventInfo.[Action]
,Warehouse.EventInfo.[Result]
,Warehouse.EventInfo.Reason
,Warehouse.EventInfo.PersonId
,Warehouse.EventInfo.Title
,Warehouse.EventInfo.FirstName
,Warehouse.EventInfo.MiddleName
,Warehouse.EventInfo.LastName
,Warehouse.EventInfo.Suffix
,Warehouse.EventInfo.Nickname
,Warehouse.EventInfo.DoorName
,Warehouse.EventInfo.DoorBehaviorName
,Warehouse.EventInfo.EnterZone
,Warehouse.EventInfo.LeaveZone
,Warehouse.EventInfo.SiteCode
,Warehouse.EventInfo.CardCode
,Warehouse.EventInfo.SiteCode + '-' + Warehouse.EventInfo.CardCode as Badge
FROM
Warehouse.EventInfo
WHERE
Warehouse.EventInfo.[Time] Between #StartTime and #EndTime
AND (1 = #PersonIdExpr OR EventInfo.PersonId IN (#PersonId))
AND WareHouse.EventInfo.ZoneHierarchy LIKE #Hierarchy
order by Time
The dataset is calling the view below:
SELECT EAC.Event.CreatedUTC AS Time
,DATEADD(MINUTE, EAC.Event.CreatedUTCOffset
, EAC.Event.CreatedUTC) AS SourceTime
, EAC.TimeZoneMap.TimeZoneShortName
, EAC.EventClass.Name AS Class
, EAC.EventCategory.Name AS Category
, EAC.EventAction.Name AS Action
, EAC.EventResult.Name AS Result
, EAC.EventReason.Name AS Reason
, EAC.Person.Id AS PersonId
, EAC.Person.Title
, EAC.Person.FirstName
, EAC.Person.MiddleName
, EAC.Person.LastName
, EAC.Person.Suffix
, EAC.Person.DisplayName AS Nickname
, EAC.Door.Name AS DoorName
, Zone_1.Name AS EnterZone
, (SELECT TOP (1) Name
FROM EAC.Zone
WHERE (Id IN (EAC.Door.Zone1Id, EAC.Door.Zone2Id))
AND (Id <> EAC.Event.ZoneId)) AS LeaveZone
, EAC.DoorBehavior.Name AS DoorBehaviorName
, EAC.Event.CardCode
, EAC.Event.SiteCode
, ISNULL(EAC.Event.Alarmed, 0) AS AlarmType
, Zone_1.ZoneHierarchy
FROM EAC.Event
INNER JOIN EAC.EventType ON EAC.EventType.Id = EAC.Event.EventTypeId
LEFT OUTER JOIN EAC.EventClass ON EAC.EventClass.Id = EAC.Event.EventClassId
LEFT OUTER JOIN EAC.EventCategory ON EAC.EventCategory.Id = EAC.EventType.CategoryId
LEFT OUTER JOIN EAC.EventAction ON EAC.EventAction.Id = EAC.EventType.ActionId
LEFT OUTER JOIN EAC.EventResult ON EAC.EventResult.Id = EAC.EventType.ResultId
LEFT OUTER JOIN EAC.EventReason ON EAC.EventReason.Id = EAC.EventType.ReasonId
LEFT OUTER JOIN EAC.Person ON EAC.Person.Id = EAC.Event.PersonId
LEFT OUTER JOIN EAC.Door ON EAC.Door.Id = EAC.Event.DoorId
LEFT OUTER JOIN EAC.Zone AS Zone_1 ON Zone_1.Id = EAC.Event.ZoneId
LEFT OUTER JOIN EAC.DoorBehavior ON EAC.DoorBehavior.Id = EAC.Door.DoorBehaviorId
LEFT OUTER JOIN EAC.Credential ON EAC.Credential.Id = EAC.Event.CredentialId
LEFT OUTER JOIN EAC.WiegandCredential ON EAC.WiegandCredential.CredentialId = EAC.Credential.Id
LEFT OUTER JOIN EAC.TimeZoneMap on EAC.TimeZoneMap.Id = EAC.Door.TimeZoneMapId
The table it is querying has millions of records but in order to get anything to come back I limited it to 100 records but it still takes 15 minutes.
When I run the report I see this in the database:
Here is the execution plan:
Execution plan
What can I do to make this report run more efficiently?
with that much LEFT OUTER JOIN It is not surprising that your query runs slow. Each join introduces complexity to your code. Besides, LEFT|RIGHT [OUTER] JOIN is much slower then regular join since it has to do all the work of an INNER JOIN (regular join) plus the extra work of null-extending the results.
Also it is impossible to make comment or pinpoint the problem without seeing explain plan of the query. Possibly you have missing indexes on tables(s)
i added indexes as well but still it is taking 13 sec
I added compound index for all the columns that i've used here
SELECT carrierbil2_.IDENTITY AS col_0_0_,
carrier4_.CARRIER_NAME AS col_1_0_,
carrier4_.IDENTITY AS col_2_0_,
carrier4_.CARRIER_ID AS col_3_0_,
shipmentor0_.EXTERNAL_REFERENCE_ID AS col_4_0_,
invoicedet5_.INVOICE_NUMBER AS col_5_0_,`enter code here`
shipmentca1_.CARRIER_REFERENCE_NUMBER AS col_6_0_,
SUM(shipmentco9_.RATED_COST) AS col_7_0_,
SUM(shipmentco9_.COST) AS col_8_0_,
invoice6_.TOTAL_PAID_AMOUNT AS col_9_0_,
invoice6_.INVOICE_GENERATED_DATE AS col_10_0_,
shipmentor0_.ACTUAL_SHIP_DATE AS col_11_0_,
bolstatus15_.BOL_STATUS_ID AS col_12_0_,
shipmentlo10_.LOCATION_NAME AS col_13_0_,
country11_.COUNTRY_NAME AS col_14_0_,
postal14_.POSTAL_CODE AS col_15_0_,
state12_.STATE_NAME AS col_16_0_,
city13_.CITY_NAME AS col_17_0_,
shipmentlo16_.LOCATION_NAME AS col_18_0_,
country17_.COUNTRY_NAME AS col_19_0_,
postal20_.POSTAL_CODE AS col_20_0_,
state18_.STATE_NAME AS col_21_0_,
city19_.CITY_NAME AS col_22_0_,
shipmentor0_.IDENTITY AS col_23_0_,
shipmentca1_.IDENTITY AS col_24_0_,
shipmentno7_.NOTE AS col_25_0_
FROM
SHIPMENT_ORDER shipmentor0_
INNER JOIN
SHIPMENT_CARRIER shipmentca1_ ON shipmentor0_.SHIPMENT_ORDER_ID = shipmentca1_.SHIPMENT_ORDER_ID
AND (shipmentca1_.IS_DELETED = 0)
LEFT OUTER JOIN
CARRIER_BILL_DETAILS carrierbil2_ ON shipmentca1_.SHIPMENT_CARRIER_ID = carrierbil2_.SHIPMENT_CARRIER_ID
LEFT OUTER JOIN
CARRIER_BILLS carrierbil3_ ON carrierbil2_.CARRIER_BILL_ID = carrierbil3_.CARRIER_BILL_ID
INNER JOIN
CARRIER carrier4_ ON shipmentca1_.CARRIER_ID = carrier4_.CARRIER_ID
LEFT OUTER JOIN
INVOICE_DETAILS invoicedet5_ ON shipmentor0_.SHIPMENT_ORDER_ID = invoicedet5_.SHIPMENT_ORDER_ID
LEFT OUTER JOIN
INVOICE invoice6_ ON invoicedet5_.INVOICE_ID = invoice6_.INVOICE_ID
LEFT OUTER JOIN
SHIPMENT_NOTES shipmentno7_ ON shipmentor0_.SHIPMENT_ORDER_ID = shipmentno7_.SHIPMENT_ORDER_ID
AND (shipmentno7_.NOTE_TYPE = 4)
LEFT OUTER JOIN
SHIPMENT_COST shipmentco8_ ON shipmentor0_.SHIPMENT_ORDER_ID = shipmentco8_.SHIPMENT_ID
LEFT OUTER JOIN
SHIPMENT_COST_DETAILS shipmentco9_ ON shipmentco8_.SHIPMENT_COST_ID = shipmentco9_.SHIPMENT_COST_ID
AND (shipmentco9_.IS_DELETED = 0)
LEFT OUTER JOIN
SHIPMENT_LOCATION shipmentlo10_ ON shipmentor0_.ORIGIN_ID = shipmentlo10_.SHIPMENT_LOCATION_ID
AND (shipmentlo10_.LOCATION_TYPE_ID = 3)
LEFT OUTER JOIN
COUNTRY country11_ ON shipmentlo10_.COUNTRY_ID = country11_.COUNTRY_ID
LEFT OUTER JOIN
STATE state12_ ON shipmentlo10_.STATE_ID = state12_.STATE_ID
LEFT OUTER JOIN
CITY city13_ ON shipmentlo10_.CITY_ID = city13_.CITY_ID
LEFT OUTER JOIN
POSTAL postal14_ ON shipmentlo10_.POSTAL_ID = postal14_.POSTAL_ID
LEFT OUTER JOIN
BOL_STATUS bolstatus15_ ON shipmentor0_.ORDER_STATUS = bolstatus15_.BOL_STATUS_ID
LEFT OUTER JOIN
SHIPMENT_LOCATION shipmentlo16_ ON shipmentor0_.DESTINATION_LOCATION_ID = shipmentlo16_.SHIPMENT_LOCATION_ID
AND (shipmentlo16_.LOCATION_TYPE_ID = 4)
LEFT OUTER JOIN
COUNTRY country17_ ON shipmentlo16_.COUNTRY_ID = country17_.COUNTRY_ID
LEFT OUTER JOIN
STATE state18_ ON shipmentlo16_.STATE_ID = state18_.STATE_ID
LEFT OUTER JOIN
CITY city19_ ON shipmentlo16_.CITY_ID = city19_.CITY_ID
LEFT OUTER JOIN
POSTAL postal20_ ON shipmentlo16_.POSTAL_ID = postal20_.POSTAL_ID
CROSS JOIN
CLIENT client21_
WHERE
shipmentor0_.CLIENT_ID = client21_.CLIENT_ID
AND bolstatus15_.SEQUENCE_ID >= 700
AND (carrierbil3_.IS_APPROVED = 0
OR carrierbil3_.IS_APPROVED IS NULL)
AND (carrierbil3_.IS_DELETED = 0
OR carrierbil3_.IS_DELETED IS NULL)
AND (carrierbil2_.IS_DELETED = 0
OR carrierbil2_.IS_DELETED IS NULL)
AND (shipmentor0_.IS_DELETED = 0
OR shipmentor0_.IS_DELETED IS NULL)
GROUP BY invoice6_.INVOICE_GENERATED_DATE , shipmentca1_.IDENTITY , invoicedet5_.INVOICE_NUMBER , invoice6_.TOTAL_PAID_AMOUNT , shipmentca1_.CARRIER_REFERENCE_NUMBER , carrier4_.CARRIER_ID , CAST(carrier4_.IDENTITY AS SIGNED) , carrier4_.CARRIER_NAME , CAST(carrierbil2_.IDENTITY AS SIGNED) , shipmentor0_.SHIPMENT_ORDER_ID , shipmentno7_.NOTE , shipmentor0_.EXTERNAL_REFERENCE_ID , shipmentlo10_.LOCATION_NAME , country11_.COUNTRY_NAME , postal14_.POSTAL_CODE , state12_.STATE_NAME , city13_.CITY_NAME , shipmentlo16_.LOCATION_NAME , country17_.COUNTRY_NAME , postal20_.POSTAL_CODE , state18_.STATE_NAME , city19_.CITY_NAME , shipmentor0_.IDENTITY
ORDER BY shipmentor0_.SHIPMENT_ORDER_ID DESC;
The indexes are mostly useless because of OR, as in
AND (carrierbil3_.IS_APPROVED = 0
OR carrierbil3_.IS_APPROVED IS NULL)
The simple way to fix that is to pick either 0 or NULL to represent the flag. Then make sure all the data is consistent, and change the WHERE to just check for the one case.
Do you really mean
CROSS JOIN
CLIENT client21_
That is likely to be a performance-killer and generate a huge resultset.
Never mind. You have the ON in WHERE. Please use ON for relations and WHERE for filtering.
WHERE
shipmentor0_.CLIENT_ID = client21_.CLIENT_ID
I see a mixture of LEFT JOIN and JOIN. Check that the LEFT JOINs really need to be LEFT; that is, the 'right' table might have missing data.
To discuss further, please provide EXPLAIN SELECT ....
Eschew over-normalization:
You have 5 tables to describe a location (name, country, postal, state, city). Instead, I recommend a single table with those 5 columns. This, alone, would get rid of 8 JOINs.
CAST(carrier4_.IDENTITY AS SIGNED) -- Can't you fix the datatype to be SIGNED, or allow the value to be UNSIGNED?
But perhaps the main performance-killer is the "explode-implode" syndrone. First, it does a lot of JOINs, building a huge intermediate table, then it collapses that by doing GROUP BY. The remedy is
SELECT ...
FROM ( SELECT SUM(...), SUM(...) FROM ... GROUP BY ... ) AS a
JOIN ((whatever else is needed));
That is, first devise a minimal "derived table" that does the GROUP BY (and/or ORDER BY and/or LIMIT). Then see what else is needed to complete the query (namely all the normalization lookups).
After you have acted on most of my comments, we can discuss whether you have the optimal indexes. (It is premature to do so now.) If so, please start a new Question; it would be too much clutter to add to this one.
First of all, that's a lot of joins. However, the main reason your query is taking a significant time is because you're adding an order by clause. You need to figure out a way to avoid it, or may be come up with a different strategy
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".
Please find below a link to the table-structure I have set up and to the query I am running.
Link to tables and query.
The present result is that only the firstnames, lastnames and "education_finished" are showing. But all the option_id's and their related lang_values still show "NULL".
The desired result:
Any suggestions how to solve?
Below is the query that you are using:
SELECT d.pf_firstname, d.pf_lastname, f.field_id, fl.option_id,
d.pf_education_finished, fl.lang_value
FROM phpbb_profile_fields_data d
LEFT JOIN phpbb_profile_fields f
ON d.pf_education_finished = f.field_name
LEFT JOIN phpbb_profile_fields_lang fl
ON f.field_id = fl.field_id
ORDER BY d.pf_lastname ASC
The reason why you are getting null value is because of this condition:
LEFT JOIN phpbb_profile_fields f
ON d.pf_education_finished = f.field_name
You are trying to join on pf_education_finished (int) field of one table and field_name (int) field of another table. Also, there are no matching values (e.g. pf_education_finished contains numbers whereas field_nameis 'education finished').
If you want the query to return something then you need to join on field_id and phpbb_profile_fields needs to have some records with matching field id, e.g.:
SELECT d.pf_firstname, d.pf_lastname, f.field_id, fl.option_id,
d.pf_education_finished, fl.lang_value
FROM phpbb_profile_fields_data d
LEFT JOIN phpbb_profile_fields f
ON d.pf_education_finished = f.field_id
LEFT JOIN phpbb_profile_fields_lang fl
ON f.field_id = fl.field_id
ORDER BY d.pf_lastname ASC
Here's the updated SQL Fiddle.
SELECT d.pf_firstname, d.pf_lastname, f.field_id, fl.option_id,
d.pf_education_finished, fl.lang_value
FROM phpbb_profile_fields_lang fl
inner JOIN phpbb_profile_fields f
ON f.field_id = fl.field_id
inner JOIN phpbb_profile_fields_data d
ON f.field_id = fl.field_id
ORDER BY d.pf_lastname ASC
This is the optional query if you want to display data from 3-4 tables but in this query names are repeats as per the count of field_id present in phpbb_profile_fields_lang.
The exact solution you are looking is, when you have the same primary key in all the tables from which you are retrieving the data.
Thank you.
I'm having trouble with a simple MySQL Query.
Here is the query:
SELECT distinct e.E_CODE, s.S_CODE, p.P_ID, p.P_NAME, p.P_FIRSTNAME, p.P_STATUS, e.E_BOSS, tp.TP_TITLE
from event_participation ep, worker p, type_participation tp, event e, section s
where ep.P_ID = p.P_ID
and s.S_ID = e.S_ID
and ep.TP_ID = tp.TP_ID
and e.E_CODE = ep.E_CODE
The problem is that ep.TP_ID sometimes has a value set to zero while tp.TP_ID has nothing with a zero ID. It's auto-increment and starts at 1 and so on.
The result is obviously that this query does not return records when the ep.TP_ID = 0 and there is no match in tp.TP_ID.
So I'm trying to figure out a way to get those results in there anyway. I was thinking of using a LEFT JOIN statement but couldn't figure out a proper way to insert it into the query.
Any advice on this matter would be greatly appreciated.
First of all, I advice you to use some general type for event_participation records without type; But, unless to take that decision, supposing you want to get all matching records between all tables but also get results with no type, you can use the following query:
SELECT DISTINCT e.E_CODE, s.S_CODE, p.P_ID, p.P_NAME, p.P_FIRSTNAME, p.P_STATUS, e.E_BOSS, tp.TP_TITLE
FROM event_participation ep
JOIN worker p ON (ep.P_ID = p.P_ID)
JOIN event e ON (e.E_CODE = ep.E_CODE)
JOIN section s ON (s.S_ID = e.S_ID)
LEFT JOIN type_participation tp ON (ep.TP_ID = tp.TP_ID)
SELECT DISTINCT e.E_CODE
, s.S_CODE
, p.P_ID
, p.P_NAME
, p.P_FIRSTNAME
, p.P_STATUS
, e.E_BOSS
, tp.TP_TITLE
FROM event_participation ep
JOIN worker p
ON p.P_ID = ep.P_ID
JOIN event e
ON e.E_CODE = ep.E_CODE
JOIN section s
ON s.S_ID = e.S_ID
LEFT
JOIN type_participation tp
ON tp.TP_ID = ep.TP_ID;