mysql short union - sql

I'm far from being a mysql guru, so need to know if there's a way to make this query faster,shorter and more compact.
(SELECT DISTINCT(cfrm.nid), f.filename, n.title, n.created
FROM content_field_raamatu_marksonad cfrm
LEFT JOIN node n ON (n.nid = cfrm.nid)
LEFT JOIN content_field_kaanepilt cfk ON (cfk.nid = n.nid)
LEFT JOIN files f ON (f.fid = cfk.field_kaanepilt_fid)
WHERE n.type = 'raamat'
AND n.status = 1
AND cfrm.field_raamatu_marksonad_value IN (102, 3348))
UNION
(SELECT DISTINCT(cfrt.nid), f.filename, n.title, n.created
FROM content_field_raamatu_teema cfrt
LEFT JOIN node n ON (n.nid = cfrt.nid)
LEFT JOIN content_field_kaanepilt cfk ON (cfk.nid = n.nid)
LEFT JOIN files f ON (f.fid = cfk.field_kaanepilt_fid)
WHERE n.type = 'raamat'
AND n.status = 1
AND cfrt.field_raamatu_teema_value = 1342)
ORDER BY `created` DESC

About the only way to rewrite it is to do the UNION before you do the LEFT JOINs:
SELECT DISTINCT x.nid, f.filename, n.title, n.created
FROM (SELECT DISTINCT cfrm.nid
FROM content_field_raamatu_marksonad AS cfrm
WHERE cfrm.field_raamatu_marksonad_value IN (102, 3348)
UNION
SELECT DISTINCT cfrt.nid
FROM content_field_raamatu_teema AS cfrt
WHERE cfrt.field_raamatu_teema_value = 1342) AS x
LEFT JOIN node AS n ON n.nid = x.nid
LEFT JOIN content_field_kaanepilt AS cfk ON cfk.nid = n.nid
LEFT JOIN files AS f ON f.fid = cfk.field_kaanepilt_fid
WHERE n.type = 'raamat'
AND n.status = 1
ORDER BY n.created DESC;
This might save dual scans of the outer joined tables. On the other hand, the optimizer might optimize it like that anyway - though I suspect it probably would not. Replacing the LEFT JOIN operations with JOIN would improve performance - if it does not affect the accuracy of the result. That depends on whether you expect there to be a file name for every row or not - at least in part.

Related

Duplicate data from select statement

I want to make a stress test to a procedure than generate a .csv file.
The problem is that i have not enough data, so i want to duplicate data in my sql select .
The query look like this:
SELECT P.FST_NAME,
P.LAST_NAME,
P.EMAIL_ADDR,
P.PERSON_UID,
PR.FST_NAME PRSP_FST_NAME,
PR.LAST_NAME PRSP_LAST_NAME,
M.X_BAPRO_DT_01,
M.X_BAPRO_DT_02,
M.X_BAPRO_DT_03,
M.X_BAPRO_MONTO,
M.X_BAPRO_NUM_01,
M.X_BAPRO_NUM_02,
M.X_BAPRO_NUM_03,
M.X_BAPRO_TEXT_01,
M.X_BAPRO_TEXT_02,
M.X_BAPRO_TEXT_03,
M.X_BAPRO_TEXT_04,
M.X_BAPRO_TEXT_05
FROM SIEBEL.S_SRC C
left join SIEBEL.S_CAMP_CON M on C.ROW_ID = M.SRC_ID
left join SIEBEL.S_DMND_CRTN_PRG T on T.ROW_ID = M.DCP_ID
left join SIEBEL.S_CONTACT P on P.ROW_ID = M.CON_PER_ID
left join SIEBEL.S_PRSP_CONTACT PR on PR.ROW_ID= M.PRSP_CON_PER_ID
WHERE
C.ROW_ID <> p_row_id
So, This query return about 100 records, i want to retrive 1000 records and i dont really care if the data is duplicated.
You can add a cross join:
FROM SIEBEL.S_SRC C
left join SIEBEL.S_CAMP_CON M on C.ROW_ID = M.SRC_ID
left join SIEBEL.S_DMND_CRTN_PRG T on T.ROW_ID = M.DCP_ID
left join SIEBEL.S_CONTACT P on P.ROW_ID = M.CON_PER_ID
left join SIEBEL.S_PRSP_CONTACT PR on PR.ROW_ID= M.PRSP_CON_PER_ID
cross join (select 1 as n from dual union all
select 2 from dual
. . .
) x
You can also use the VALUE clause to construct the little "muliplier"-table as shown below:
SELECT ...
FROM SIEBEL.S_SRC C
left join SIEBEL.S_CAMP_CON M on C.ROW_ID = M.SRC_ID
left join SIEBEL.S_DMND_CRTN_PRG T on T.ROW_ID = M.DCP_ID
left join SIEBEL.S_CONTACT P on P.ROW_ID = M.CON_PER_ID
left join SIEBEL.S_PRSP_CONTACT PR on PR.ROW_ID= M.PRSP_CON_PER_ID
cross join (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) tabl(n)

SQL join not returning the correct data

Im trying to build some test cases in SQL. The problem is when im trying to join some table with a left join (wich if my understanding is correct should return both the matching and nonmatching row) when im trying to get the data with no matching ID, no data is returned. Here is the code :
select
E.ID_EVENEMENT,
t1.dateRecente as date_Star,
virage_c.no_contr,
t2.id as id_Univers,
t2.dateRecente as date_Univers,
t3.NUMERO_DOSSIER_STAR,
t3.dateRecente as Date_factcan,
t3.dateLimite,
t2.ID_PERSONNE_UNIVERS,
t1.ID_PERSONNE_STAR
FROM
STAR.EVENEMENT e
left join VIRAGE.CONTRAT virage_c
on e.NO_CONTRAT_OFFICIEL = to_char(virage_c.no_contr)
inner join
( SELECT
e.ID_EVENEMENT,
ep.ID_EVEN_INDIVIDU as ID_PERSONNE_STAR,
GREATEST( e.dt_creation,
NVL(e.DT_MODIF_STA_ELI, TO_DATE(1,'j')),
NVL(max(nt.dt_maj), TO_DATE(1,'j')),
NVL(max(ser.DT_CREATION), TO_DATE(1,'j')),
NVL(max(SER.DT_MAJ), TO_DATE(1,'j')),
NVL(max(aut.dt_transmis), TO_DATE(1,'j')),
NVL(max(AUT.DT_CREATION), TO_DATE(1,'j')) ) dateRecente
FROM
STAR.EVENEMENT e
left join STAR.Note nt
on e.ID_EVENEMENT = nt.ID_EVEN
left join STAR.SERVICE ser
on e.ID_EVENEMENT = ser.ID_EVEN
left join STAR.AUTORISATION aut
on ser.id_service = aut.id_service
left join STAR.DOCUMENT doc
on e.ID_EVENEMENT = doc.ID_EVENEMENT
left join STAR.ETAT ett
on e.ID_EVENEMENT = ett.ID_EVENEMENT
left join STAR.EVENEMENT_PARTICIPANT ep
on e.ID_EVENEMENT = ep.ID_EVENEMENT
GROUP BY
e.ID_EVENEMENT,
e.dt_creation,
e.DT_MODIF_STA_ELI,
ep.ID_EVEN_INDIVIDU ) t1
on t1.ID_EVENEMENT = E.ID_EVENEMENT
left JOIN
( SELECT
sf.STAREVENTNUMBER,
c.id,
par.ID as ID_PERSONNE_UNIVERS,
GREATEST( c.UPDATEDATE,
max(NVL(ca.UPDATEDATE, TO_DATE(1, 'J'))),
max(NVL(bo.UPDATEDATE, TO_DATE(1, 'J'))),
max(NVL(a.UPDATEDATE, TO_DATE(1, 'J'))),
max(NVL(p.UPDATEDATE, TO_DATE(1, 'J'))),
max(NVL(p.RELEASEDATE, TO_DATE(1, 'J'))),
max(NVL(p.PAYMENTDATE, TO_DATE(1, 'J'))) ) dateRecente
FROM
CV_CLAIMS_TRAVEL.STAR_FILE sf
join CV_CLAIMS_TRAVEL.CLAIM c
on sf.claimid = c.id
left join CV_CLAIMS_TRAVEL.BENEFIT_OPTION bo
on c.id = BO.CLAIMID
left join CV_CLAIMS_TRAVEL.ADJUDICATION a
on bo.id = a.BENEFITOPTIONID
left join CV_CLAIMS_TRAVEL.CLAIM_ACTIVITY ca
on c.id = CA.CLAIMID
left join CV_CLAIMS_TRAVEL.CLAIM_RELATIONSHIP cr
on c.id = CR.CLAIMID
left join CV_CLAIMS_TRAVEL.PAYEE pa
on cr.id = PA.CLAIMRELATIONSHIPID
left join CV_CLAIMS_TRAVEL.PAYMENT p
on pa.id = P.PAYEEID
left join CV_CLAIMS_TRAVEL.PARTY par
on par.ID = sf.PARTYID
WHERE
c.PRIMARYSTATUSLID in ('CLAIM_PRIMARY_STATUS:0000000003','CLAIM_PRIMARY_STATUS:0000000001')
OR ( c.PRIMARYSTATUSLID = 'CLAIM_PRIMARY_STATUS:0000000004'
AND bo.BENEFITOPTIONSTATUSLID in ('BENEFIT_OPTION_STATUS:0000000010',
'BENEFIT_OPTION_STATUS:0000000060',
'BENEFIT_OPTION_STATUS:0000000030')
)
group by
sf.STAREVENTNUMBER,
c.id,
c.UPDATEDATE,
par.ID ) t2
on e.ID_EVENEMENT = t2.STAREVENTNUMBER
LEFT JOIN
( SELECT DISTINCT
fact.NUMERO_DOSSIER_STAR,
GREATEST( to_date(fact.VSTDTCHG,'yyyymmdd'),
to_date(fact.VSTDICHK,'yyyymmdd'),
to_date(decode(fact.VSTDIFIN,0,19000101,
decode(substr(fact.VSTDIFIN,5),
'0230', substr(fact.VSTDIFIN,1,4)
|| '0301',fact.VSTDIFIN)),'yyyymmdd') ) DateRecente,
DECODE( virage_cont.id_cont,
null,add_months(sysdate,-7*12),
add_months(sysdate,-15*12)) dateLimite
FROM
FACTCAN.XC4DSAV fact
LEFT JOIN VIRAGE.CONTRAT virage_cont
on fact.VSTNOCNT_VIRAGE = virage_cont.NO_CONTR
where
fact.NUMERO_DOSSIER_STAR is not null ) t3
on e.ID_EVENEMENT = t3.NUMERO_DOSSIER_STAR
WHERE
t1.dateRecente < add_months(sysdate, -7*12)
AND t2.dateRecente < add_months(sysdate, -7*12)
AND virage_c.id_cont is null
AND t2.ID_PERSONNE_UNIVERS is not null
AND t1.ID_PERSONNE_STAR is null
AND t3.dateRecente < t3.dateLimite
FETCH
FIRST 1000 ROWS ONLY;
When I'm trying to get the results from an event with either
t1.ID_PERSONNE_STAR or t2.ID_PERSONNE_UNIVERS is null, the query isn't returning anything when it should in fact return some data. The is not null work as intended though. Any idea?
I updated the readability of the query. Also, as noted by others, you have to be careful about the WHERE clause. The issue you are probably running into is your where clauses for the T1, T2 and T3 for left-joins... Move these up to those joins... ex
where you have
left join (rest of the left-join subquery with alias ) t1
on t1.ID_EVENEMENT = E.ID_EVENEMENT
change to
on t1.ID_EVENEMENT = E.ID_EVENEMENT
AND t1.dateRecente < add_months(sysdate, -7*12)
This way, the date requirement is part of the LEFT-JOIN. By having that in the WHERE clause is turning it into an INNER JOIN.
You can leave the T1 "IS NULL" test at the where clause portion because you are explicitly expecting no matching records.
Check similar situations for your other left-joins... move the CRITERIA to the JOIN/ON clause and remove from the WHERE. The where clause SHOULD have the "IS NULL" for final expectation.

why selecting particular columns from same table slows down query performance significantly?

I have SELECT statement that querying columns from tblQuotes. Why if I am selecting columns a.ProducerCompositeCommission and a.CompanyCompositeCommission, then query spinning forever.
Execution plans with and without those columns are IDENTICAL!
If I commented them out - then it brings result for 1 second.
SELECT
a.stateid risk_state1,
--those columns slows down performance
a.ProducerCompositeCommission,
a.CompanyCompositeCommission,
GETDATE() runDate
FROM
tblQuotes a
INNER JOIN
lstlines l ON a.LineGUID = l.LineGUID
INNER JOIN
tblSubmissionGroup tsg ON tsg.SubmissionGroupGUID = a.SubmissionGroupGuid
INNER JOIN
tblUsers u ON u.UserGuid = tsg.UnderwriterUserGuid
INNER JOIN
tblUsers u2 ON u2.UserGuid = a.UnderwriterUserGuid
LEFT OUTER JOIN
tblFin_Invoices tfi ON tfi.QuoteID = a.QuoteID AND tfi.failed <> 1
INNER JOIN
lstPolicyTypes lpt ON lpt.policytypeid = a.policytypeid
INNER JOIN
tblproducercontacts prodC ON prodC.producercontactguid = a.producercontactguid
INNER JOIN
tblProducerLocations pl ON pl.producerlocationguid = prodc.producerlocationguid
INNER JOIN
tblproducers prod ON prod.ProducerGUID = pl.ProducerGUID
LEFT OUTER JOIN
Catalytic_tbl_Model_Analysis aia ON aia.ImsControl = a.controlno
AND aia.analysisid = (SELECT TOP 1 tma2.analysisid
FROM Catalytic_tbl_Model_Analysis tma2
WHERE tma2.imscontrol = a.controlno)
LEFT OUTER JOIN
Catalytic_tbl_RDR_Analysis rdr ON rdr.ImsControl = a.controlno
AND rdr.analysisid = (SELECT TOP 1 tma2.analysisid
FROM Catalytic_tbl_RDR_Analysis tma2
WHERE tma2.imscontrol = a.controlno)
LEFT OUTER JOIN
tblProducerContacts mnged ON mnged.producercontactguid = ProdC.ManagedBy
LEFT OUTER JOIN
lstQuoteStatusReasons r1 ON r1.id = a.QuoteStatusReasonID
WHERE
l.LineName = 'EARTHQUAKE'
AND CAST(a.EffectiveDate AS DATE) >= CAST('2017-01-01' AS DATE)
AND CAST(a.EffectiveDate AS DATE) <= CAST('2017-12-31' AS DATE)
ORDER BY
a.effectiveDate
The execution plan can be found here:
https://www.brentozar.com/pastetheplan/?id=rJawDkTx-
I ran sp_help and this is what I see:
What exactly wrong with those columns?
I dont use them in a JOIN or anything. Why such bahaviour?
Table Size:
Indexes on table tblQuotes

MSSQL Query get latest value from two tables faster

This query pulls the timestamp (DT_CREATED) from two different tables and selecting the most recent timestamp. The INCIDENT_AUDIT_HISTORY table is quite large and even though I've improved performance by 10 seconds by adding indexes my query still takes over 20 seconds to run, which is longer than desired for the application. I'm wondering if there is a more efficient way to write this query?
SELECT i.NUMBER, i.PROBLEM, st.LABEL AS STATUS, i.ID_ASSIGNEE, r.LNAME + ', ' + r.FNAME AS ASIGNEE, c.LNAME + ', ' + c.FNAME AS CUST_NAME,
p.LABEL AS PRIORITY, i.DT_CREATED,
(SELECT MAX(DT_CREATED) AS LAST_WORK
FROM (SELECT TOP (1) DT_CREATED
FROM dbo.REP_WORK_HISTORY AS b
WHERE (i.NUMBER = INCIDENT_NUMBER) AND (ID_OWNER = r.ID)
ORDER BY DT_CREATED DESC
UNION
SELECT TOP (1) DT_CREATED
FROM dbo.INCIDENT_AUDIT_HISTORY AS c
WHERE (i.NUMBER = INCIDENT_NUMBER) AND (ID_OWNER = r.ID)
ORDER BY DT_CREATED DESC) AS a) AS LAST_HISTORY, g.GROUP_NAME FROM dbo.REPS AS r RIGHT OUTER JOIN
dbo.GROUPS AS g ON r.ID_DEFAULT_GROUP = g.ID RIGHT OUTER JOIN
dbo.INCIDENTS AS i ON r.ID = i.ID_ASSIGNEE LEFT OUTER JOIN
dbo.CUSTOMERS AS c ON i.ID_CUSTOMER = c.ID LEFT OUTER JOIN
dbo._PRIORITIES AS p ON i.PRIORITY = p.ID LEFT OUTER JOIN
dbo.INCIDENT_STATUSES AS st ON i.ID_STATUS = st.ID WHERE (st.TYPE <> 2) AND (st.TYPE <> 16)

Choose the greater of either left or right side of 2 queries

I have the following union query that queries for the most recent date of a column if it exists:
SELECT TOP 1 m.sentdate AS 'calltreelastsignedoff'
FROM Incidents i
INNER JOIN Plans p ON i.planuid = p.uid
INNER JOIN IncidentMessages im ON i.uid = im.incidentuid
INNER JOIN Messages m ON im.messageuid = m.uid
WHERE p.uid = '031E3346-2921-426E-9494-1111111111'
UNION
SELECT TOP 1 m.sentdate AS 'calltreelastsignedoff'
FROM Incidents i
INNER JOIN PlanExercises pe ON i.planexerciseuid = pe.uid
INNER JOIN IncidentMessages im ON i.uid = im.incidentuid
INNER JOIN Messages m ON im.messageuid = m.uid
WHERE pe.planuid = '031E3346-2921-426E-9494-1111111111'
This will return 2 values if each query returns a top 1 result.
What I really want is to select the top 1 of the combined query.
How can I perform a select on the unioned query?
try this:
You could do this with a derived table
select top 1 from
(
SELECT TOP 1 m.sentdate AS 'calltreelastsignedoff'
FROM Incidents i
INNER JOIN Plans p ON i.planuid = p.uid
INNER JOIN IncidentMessages im ON i.uid = im.incidentuid
INNER JOIN Messages m ON im.messageuid = m.uid
WHERE p.uid = '031E3346-2921-426E-9494-1111111111'
UNION
SELECT TOP 1 m.sentdate AS 'calltreelastsignedoff'
FROM Incidents i
INNER JOIN PlanExercises pe ON i.planexerciseuid = pe.uid
INNER JOIN IncidentMessages im ON i.uid = im.incidentuid
INNER JOIN Messages m ON im.messageuid = m.uid
WHERE pe.planuid = '031E3346-2921-426E-9494-1111111111'
)a
order by <col>