WITH tst
AS (
SELECT nz.sPostcode op
,zp.nZoneCountryID
,zp.sPostcode
,zp.nZoneID
,zp.nInjectionID
FROM dbo.tblZonePostcode zp
INNER JOIN tblNewZone nz ON nz.nPostcodeID = zp.NewZoneId
WHERE CHARINDEX('%', zp.sPostcode) = 1
AND zp.sPostcode IS NOT NULL
AND isnumeric(zp.sPostcodeRange) = 0
)
SELECT *
INTO #tmptst
FROM tst;
CREATE INDEX idx_sPostcode12 ON #tmptst (sPostcode);
CREATE INDEX idx_x1 ON #tmptst (nZoneCountryID);
CREATE INDEX idx_x2 ON #tmptst (nInjectionID);
CREATE INDEX idx_x3 ON #tmptst (nZoneID);
UPDATE #tmprec
SET calculatedPostCodeZone = (
SELECT TOP 1 zp.op
FROM #tmptst zp
WHERE zp.nZoneCountryID = CalculatedCountryId
AND zp.nInjectionID = CalculatedinjectionPointId
AND zp.nZoneID = CalculatedZoneId
AND CHARINDEX(zp.sPostcode, sConsigneePostcodeFirst) = 1
)
WHERE CalculatedRateChartGroupID > 0
AND calculatedRatechartValues IS NULL
AND calculatedPostCodeZone IS NULL
AND CalculationStatus IS NULL
AND 0 < (
SELECT count(1)
FROM #tmptst
);
In total with tst, in total contains 85k records and #tmprec contains 255k records. Objective of above query is to get matchig postcode from tblNewZone for records postcode starting with matching sConsigneePostcodeFirst.
Issue is above query is taking 7 minutes to execute. I have added Index to the query , tried like query, tried Text search Index.
Please let me know if any thing I can do to improve the query.
Related
Hello kind people of the internet.
I am wrecking my head trying to figure out why the optimiser isn't using my index for my query on Amazon Aurora. The query is dynamically created based on a report users have created through an applications UI, so I can't change the query per se.
The query uses these qualifiers
WHERE
table_in_question.deleted = 0
ORDER BY
table_in_question.date_modified DESC,
table_in_question.id DESC
I have an index, "my_index", which indexes these specific fields (table_in_question fields deleted, date_modified, ID) but MySQL doesn't use it.
The query takes approx 1200 ms to run. If I add FORCE INDEX (my_index) it takes about 120ms. Arguably about 10x faster - but unless I use force index, it doesn't use it.
Around 1 million rows are returned according to EXPLAIN, so I don't think it's a case of not using the index because of a low amount of rows being returned is the case.
The full query is
SELECT
case when some_table.id IS NOT NULL then some_table.id else "" end my_favorite,
table_in_question.date_entered,
table_in_question.name,
table_in_question.description,
table_in_question.pr_is_read,
table_in_question.pr_is_approved,
table_in_question.parent_type,
table_in_question.parent_id,
table_in_question.id,
table_in_question.date_modified,
table_in_question.assigned_user_id,
table_in_question.created_by
FROM
table_in_question
INNER JOIN (
SELECT
tst.team_user_is_member_of
FROM
team_sets_teams tst
INNER JOIN team_memberships team_membershipstable_in_question ON (
team_membershipstable_in_question.team_id = tst.team_id
)
AND (team_membershipstable_in_question.user_id = 'UUID')
AND (team_membershipstable_in_question.deleted = 0)
GROUP BY
tst.team_user_is_member_of
) table_in_question_tf ON table_in_question_tf.team_user_is_member_of = table_in_question.team_user_is_member_of
LEFT JOIN systemfavourites sf_table_in_question ON (sf_table_in_question.module = 'table_in_question')
AND (sf_table_in_question.record_id = table_in_question.id)
AND (sf_table_in_question.assigned_user_id = 'UUID')
AND (sf_table_in_question.deleted = '0')
INNER JOIN opportunities jt1_table_in_question ON (table_in_question.opportunity_id = jt1_table_in_question.id)
AND (jt1_table_in_question.deleted = 0)
LEFT JOIN another_table jt1_table_in_question_cstm ON jt1_table_in_question_cstm.id_c = jt1_table_in_question.id
LEFT JOIN systemfavourites table_in_question_favorite ON (table_in_question.id = table_in_question_favorite.record_id)
AND (table_in_question_favorite.deleted = '0')
AND (table_in_question_favorite.module = 'table_in_question')
AND (table_in_question_favorite.created_by = 'UUID')
LEFT JOIN users some_table ON (
some_table.id = table_in_question_favorite.modified_user_id
)
AND (some_table.deleted = 0)
WHERE
table_in_question.deleted = 0
ORDER BY
table_in_question.date_modified DESC,
table_in_question.id DESC
;
EXPLAIN shows this
id
select_type
table
partitions
type
possible_keys
key
key_len
ref
rows
filtered
Extra
1
PRIMARY
table_in_question
ALL
idx_table_in_question_tmst_id
968234
10.0
Using where; Using temporary; Using filesort
Can anyone help explain how I make an index it will actually use by default?
Thanks.
I have this query, and one of its column is a subquery that should be bringing a list of values using a listagg function. This list has its starting point as the S.ID_ORGAO_INTELIGENCIA value. The list is a should be, it always has values.
The listagg function is consuming an inline view that uses a window function to create the list.
select *
from (
SELECT DISTINCT S.ID_SOLICITACAO,
S.NR_PROTOCOLO_SOLICITACAO,
S.DH_INCLUSAO,
S.ID_USUARIO,
U.NR_CPF,
OI.ID_MODULO,
OI.ID_ORGAO_INTELIGENCIA,
OI.NO_ORGAO_INTELIGENCIA,
R.ID_ATRIBUICAO,
P.ID_PERMISSAO,
1 AS TIPO_NOTIFICACAO,
(
select LISTAGG(oc6.ID_ORGAO_INTELIGENCIA || '-' || oc6.ord || '-', '; ') WITHIN GROUP (ORDER BY oc6.ord) eai
from (
SELECT oc1.ID_ORGAO_INTELIGENCIA,
oc1.ID_ORGAO_INTELIGENCIA_PAI,
oc1.SG_ORGAO_INTELIGENCIA,
rownum as ord
FROM TB_ORGAO_INTERNO oc1
WHERE oc1.DH_EXCLUSAO is null
-- THE VALUE FROM S.ID_ORGAO_INTELIGENCIA IS NOT AVAILBLE HERE
START WITH oc1.ID_ORGAO_INTELIGENCIA = S.ID_ORGAO_INTELIGENCIA
CONNECT BY prior oc1.ID_ORGAO_INTELIGENCIA_PAI = oc1.ID_ORGAO_INTELIGENCIA
) oc6) aproPrec
FROM TB_SOLICITACAO S
INNER JOIN TB_ORGAO_INTERNO OI ON S.ID_ORGAO_INTELIGENCIA = OI.ID_ORGAO_INTELIGENCIA
INNER JOIN TB_RELACIONAMENTO_ATRIBUICAO R
ON (R.ID_MODULO = OI.ID_MODULO AND R.ID_ORGAO_INTELIGENCIA IS NULL AND
R.ID_SOLICITACAO IS NULL)
INNER JOIN TB_PERMISSAO P
ON (P.ID_USUARIO = :usuario AND P.ID_ORGAO_INTELIGENCIA = :orgao AND
P.ID_ATRIBUICAO = R.ID_ATRIBUICAO)
INNER JOIN TB_USUARIO U ON (U.ID_USUARIO = S.ID_USUARIO)
WHERE 1 = 1
AND U.DH_EXCLUSAO IS NULL
AND P.DH_EXCLUSAO IS NULL
AND S.DH_EXCLUSAO IS NULL
AND OI.DH_EXCLUSAO IS NULL
AND R.ID_ATRIBUICAO IN :atribuicoes
AND P.ID_STATUS_PERMISSAO = 7
AND OI.ID_MODULO = 1
AND S.ID_STATUS_SOLICITACAO IN (1, 2, 5, 6)
and s.ID_ORGAO_INTELIGENCIA in (SELECT DISTINCT o.ID_ORGAO_INTELIGENCIA
FROM TB_ORGAO_INTERNO o
WHERE o.DH_EXCLUSAO IS NULL
START WITH o.ID_ORGAO_INTELIGENCIA = 3
CONNECT BY PRIOR o.ID_ORGAO_INTELIGENCIA = o.ID_ORGAO_INTELIGENCIA_PAI)
);
The problem is that the aproPrec column is always returning null as its result.
If I force the criteria to have the S.ID_ORGAO_INTELIGENCIA hardcoded, the list returns its true value.
If I chance this:
START WITH oc1.ID_ORGAO_INTELIGENCIA = S.ID_ORGAO_INTELIGENCIA
To this:
START WITH oc1.ID_ORGAO_INTELIGENCIA = 311
where 311 is the value that the S.ID_ORGAO_INTELIGENCIA column really has.
Is there a way to make this query works as 'I think' it should work?
To make it work, I changed the subquery by this another one:
(
select qt_.*
from (
SELECT QRY_NAME.*,
rownum as ord
FROM (
SELECT oc1.ID_ORGAO_INTELIGENCIA,
oc1.ID_ORGAO_INTELIGENCIA_PAI,
connect_by_root (oc1.ID_ORGAO_INTELIGENCIA) as root
FROM TB_ORGAO_INTERNO oc1
CONNECT BY NOCYCLE PRIOR oc1.ID_ORGAO_INTELIGENCIA_PAI = oc1.ID_ORGAO_INTELIGENCIA
) QRY_NAME
WHERE root = s.ID_ORGAO_INTELIGENCIA
) qt_
)
I am using StandardSQL in BigQuery. I am writing a scheduled query which inserts records into table (2). Now, given that it's sceduled, I am trying to figure out how to update records in table (2) from the sceduled query, which is always inserting records into table (2).
In particular, when there is a record in table (2) but not generated by my query then I want to update table (2) and a boolean column to No.
Below is my query, where in the query would I add the update logic for table (2)?
INSERT INTO record (airport_name, icao_address, arrival, flight_number, origin_airport_icao, destination_airport_icao)
WITH
planes_stopped_in_airport AS (
SELECT
p.IATA_airport_code,
p.airport_name,
p.airport_ISO_country_code,
p.ICAO_airport_code,
timestamp,
a.icao_address,
a.latitude,
a.longitude,
a.altitude_baro,
a.speed,
heading,
callsign,
source,
a.collection_type,
vertical_rate,
squawk_code,
icao_actype,
flight_number,
origin_airport_icao,
destination_airport_icao,
scheduled_departure_time_utc,
scheduled_arrival_time_utc,
estimated_arrival_time_utc,
tail_number,
ingestion_time
FROM
`updates` a
JOIN
Polygons p
ON
1 = 1
WHERE
a.timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 20 MINUTE) and a.timestamp <= CURRENT_TIMESTAMP()
AND ( latitude IS NULL
AND longitude IS NULL
AND callsign IS NULL
AND speed IS NULL
AND heading IS NULL
AND altitude_baro IS NULL) IS FALSE
AND ST_DWithin( ST_GeogFromText( polygon ),
ST_GeogPoint(a.longitude,
a.latitude),
10)
AND a.collection_type = '1' -- and speed < 50
AND (origin_airport_icao IS NULL
AND destination_airport_icao IS NULL) IS FALSE )
SELECT
p.airport_name,
icao_address,
MIN(timestamp) AS Arrival,
flight_number,
origin_airport_icao,
destination_airport_icao
FROM
planes_stopped_in_airport p
WHERE
flight_number NOT IN (SELECT Distinct flight_number
FROM `table(2)`
)
GROUP BY
icao_address,
p.airport_name,
flight_number,
origin_airport_icao,
destination_airport_icao
HAVING
flight_number IS NOT NULL
ORDER BY
airport_name,
arrival
You can probably do it with MERGE statement, see details in https://cloud.google.com/bigquery/docs/reference/standard-sql/dml-syntax#merge_statement.
If I understood your requirements correctly, you need something like
MERGE dataset.Destination T
USING (SELECT * ...) S
ON T.key = S.key
WHEN MATCHED THEN
UPDATE SET T.foo = S.foo, T.bool_flag = FALSE
WHEN NOT MATCHED THEN
INSERT ...
This is the query I am using to update a column with value from another table :
UPDATE SPICES A
SET A.description = (SELECT CODE
FROM CHILLY B
WHERE SUBSTR(A.description,1,4) = TRIM(B.desc123))
WHERE EXISTS (SELECT 1
FROM CHILLY B
WHERE SUBSTR(A.description,1,4) = TRIM(B.desc123));
But this is not what I want . The requirement is to update the first 4 characters of description with the new value (CODE) from table CHILLY.
Any suggestions? new to writing queries.
You should use a concatenation operator for adding the rest of description
UPDATE SPICES A
SET A.description = (SELECT CODE
FROM CHILLY B
WHERE SUBSTR(A.description,1,4) = TRIM(B.desc123)) || SUSBSTR(A.description, 5, 255 )
WHERE EXISTS (SELECT 1
FROM CHILLY B
WHERE SUBSTR(A.description,1,4) = TRIM(B.desc123));
Refer Table WORKQUEUELOG with columns (ID,QueueTypeId,CreateDateTime,WorkId,InQ,OutQ)
There is an index available for (QueueTypeId,CreateDateTime,Id)
When trying to read the first X number of records with following query it is going for a full table search.
OPEN a_CursorHandle FOR
SELECT * FROM (
SELECT * FROM WORKQUEUELOG tbl
WHERE EX_CLS_WQLOG.FILTER(
tbl.QueueTypeId,
tbl.CreateDateTime,
NULL) = 1
AND EX_CLS_WQLOG.VALIDATION(
tbl.ID ,
tbl.WorkId ,
tbl.InQ ) = 1
ORDER BY tbl.QueueTypeId ASC,tbl.CreateDateTime ASC,tbl.Id ASC)
WHERE ROWNUM <= a_MaxCount;
We changed the query as following and started using the index for reading.
ie Validaiton function first and filter function as second.
OPEN a_CursorHandle FOR
SELECT * FROM (
SELECT * FROM WORKQUEUELOG tbl
WHERE EX_CLS_WQLOG.VALIDATION(
tbl.ID ,
tbl.WorkId,
tbl.InQ ) = 1
AND EX_CLS_WQLOG.FILTER(
tbl.QueueTypeId,
tbl.CreateDateTime,
NULL) = 1
ORDER BY tbl.QueueTypeId ASC,tbl.CreateDateTime ASC,tbl.Id ASC)
WHERE ROWNUM <= a_MaxCount;
What is the order of processing the SQL statement in oracle .? left to right or right to left.
From the above example this seems to be right to left . is this a consistent behavior. Is there any other efficient way to write this query.?