Optimising MYSQL query with row number - mysql

SELECT o.* FROM ( SELECT
#rownum := #rownum + 1 RN,
i.* FROM<br>
(
SELECT
#rownum:=0
)
r,<br>
(
SELECT DISTINCT<br>
CG_MGR_USR.MANAGER_NAME,<br>
CG_MGR_USR.PARAM_NAME,<br>
USR_TR_DATA.USER_ID,<br>
CG_MGRS.FIRST_NAME,<br>
CG_MGRS.LAST_NAME,<br>
CC_GENOBJ.OBJNAME,<br>
USR_TR_DATA.RISK_ID,<br>
USR_TR_DATA.VERSION_ID,<br>
T_RISK.RISK_DESCR,<br>
CC_RISKT.RISK_ID CC_RISK,<br>
CC_RISKT.DESCN,<br>
USR_TR_DATA.SYSTEM_ID,<br>
T_STATUS.STATUS,<br>
USR_TR_DATA.COUNTS,<br>
SYSTEMS.SYSTEM_NAME<br>
FROM
TABLE_USR_TR_DATA USR_TR_DATA<br>
LEFT OUTER JOIN TABLE_CC_GENOBJ CC_GENOBJ<br>
ON
CC_GENOBJ.GENOBJTP = 1
AND CC_GENOBJ.SYSTEM_ID IN<br>
(
SELECT
sys_id
FROM
TABLE_CS_SYSTEM
WHERE
cs_sys_id =USR_TR_DATA.system_id
AND is_primary='Y'
)<br>
AND CC_GENOBJ.GENOBJID = USR_TR_DATA.USER_ID,<br>
TABLE_RISK T_RISK<br>
LEFT OUTER JOIN TABLE_CC_RISKT CC_RISKT
ON<br>
CC_RISKT.LANG = 'EN'
AND T_RISK.CC_RISK_ID = CC_RISKT.RISK_ID,<br>
TABLE_CG_MGR_USR CG_MGR_USR,<br>
TABLE_CG_MGRS CG_MGRS,<br>
TABLE_STATUS T_STATUS,<br>
TABLE_CS_SYSTEM CS_SYSTEMS,<br>
TABLE_SYSTEMS SYSTEMS<br>
WHERE
USR_TR_DATA.RISK_ID = T_RISK.RISK_ID<br>
AND USR_TR_DATA.VERSION_ID = T_RISK.VERSION_ID<br>
AND CG_MGR_USR.USER_NAME = USR_TR_DATA.USER_ID<br>
AND CG_MGR_USR.SYSTEM_ID = CS_SYSTEMS.SYS_ID<br>
AND CG_MGRS.MANAGER_NAME = CG_MGR_USR.MANAGER_NAME<br>
AND CG_MGRS.PARAM_NAME =CG_MGR_USR.PARAM_NAME<br>
AND CG_MGRS.SYSTEM_ID = CG_MGR_USR.SYSTEM_ID<br>
AND CS_SYSTEMS.CS_SYS_ID = USR_TR_DATA.SYSTEM_ID<br>
AND CS_SYSTEMS.IS_PRIMARY = 'Y'<br>
AND T_STATUS.SEQ_NO = USR_TR_DATA.STATUS_ID<br>
AND SYSTEMS.SYSTEMS_ID = USR_TR_DATA.SYSTEM_ID<br>
AND CG_MGR_USR.MANAGER_NAME IN( 'SAPUSER' )<br>
AND T_STATUS.STATUS IN( 'IN-PROCESS', 'OPEN' )<br>
AND USR_TR_DATA.COUNTS >= 1<br>
ORDER BY
USER_ID,
SYSTEM_ID,
RISK_ID,
VERSION_ID,
CC_RISK,
STATUS,
COUNTS ASC
)
i ) o <br>WHERE o.RN >= 1 AND o.RN <= 10
It is taking too much time for to fetch only 10 records.

Related

Parentheses in mysql query giving different results

I have a query that is giving me different results when i enclosed it in Parentheses, however when I run it without Parentheses its giving me different results. I want to apply Union in between so I have to use Parentheses as without union doesn't work.
The query is as follows:
SELECT Distinct
recurring_billing.id,
recurring_billing.kid_id,
recurring_billing.class_id,
recurring_billing.app_id,
recurring_billing.Region_ID,
CC.month_name,
CC.billing_year,
CASE
WHEN
CC.month_name = recurring_billing.billing_month
AND CC.billing_year = recurring_billing.billing_year
THEN
recurring_billing.billing_status
ELSE
'Pending'
END
AS billing_status, tblkids.kid_name, tblkids.kid_Lastname, tblkids.kid_EMail, tbl_app.app_CCExp AS cc_exp, tbl_app.app_CCName AS cc_name, tbl_app.app_CCNumber AS cc_number, tbl_app.app_CCType AS cc_type, tblclasses.cla_EndDate, tblclassdays.classday_day, CC.remainingclasses, tbl_app.cost_per_class, CC.remainingclasses * tbl_app.cost_per_class AS cost_amount,
CASE
WHEN
OP.override_amt IS NOT NULL
THEN
OP.override_amt
ELSE
CC.remainingclasses * tbl_app.cost_per_class
END
AS pmt_amount,
CASE
WHEN
OP.process_payment = False
THEN
OP.process_payment
ELSE
True
END
AS process_payment
FROM
recurring_billing
LEFT JOIN
tblkidsxclass
ON recurring_billing.kid_id = tblkidsxclass.kxc_kidid
AND recurring_billing.app_id = tblkidsxclass.kxc_appid
LEFT JOIN
tbl_app
ON recurring_billing.app_ID = tbl_app.app_ID
LEFT JOIN
tblkids
ON recurring_billing.kid_id = tblkids.kid_ID
LEFT JOIN
tblclasses
ON recurring_billing.class_id = tblclasses.cla_ID
LEFT JOIN
tblclassdays
ON tblclasses.cla_ID = tblclassdays.classday_classID
INNER JOIN
(
SELECT
MONTHNAME(classday_day) AS month_name,
YEAR(classday_day) AS billing_year,
cla_ID,
COUNT(classday_classid) AS remainingclasses,
c.cost_per_class AS cost_per_class,
COUNT(classday_classid) * cost_per_class AS TotalClassCost
FROM
tblclassdays
JOIN
(
SELECT
tblclasses.cla_ID,
tblclasses.cost_per_class,
tblclasses.cla_nextclass AS next1,
tblclasses_1.cla_nextclass AS next2
FROM
tblclasses
LEFT JOIN
tblclasses AS tblclasses_1
ON tblclasses.cla_nextclass = tblclasses_1.cla_ID
WHERE
tblclasses.cla_ID IN
(
SELECT DISTINCT
recurring_billing.class_id
FROM
recurring_billing
LEFT JOIN
tblkidsxclass
ON recurring_billing.kid_id = tblkidsxclass.kxc_kidid
AND recurring_billing.app_id = tblkidsxclass.kxc_appid -- LEFT JOIN tblkids ON recurring_billing.kid_id = tblkids.kid_ID
LEFT JOIN
tblclasses
ON recurring_billing.class_id = tblclasses.cla_ID -- LEFT JOIN tblclassdays ON tblclasses.cla_ID = tblclassdays.classday_classID
WHERE
ISNULL(tblkidsxclass.kxc_dropoutdate)
AND tblkidsxclass.pmt_option = 'Recurring'
AND tblclasses.cla_active = TRUE -- AND tblclasses.cla_EndDate >= NOW()
GROUP BY
recurring_billing.id
)
)
c
ON tblclassdays.classday_classid IN
(
c.cla_ID,
c.next1,
c.next2
)
WHERE
tblclassdays.classday_noclass = FALSE
AND MONTH(classday_day) = 11
AND YEAR(classday_day) = 2020
AND
(
CONCAT(CAST(classday_day AS DATE), ' ', CAST(classday_endtime AS TIME)) > CAST(CURDATE() AS DATETIME)
)
GROUP BY
cla_ID
)
CC
ON CC.cla_ID = tblclassdays.classday_classID
LEFT JOIN
override_payments OP
ON recurring_billing.app_id = OP.app_id
AND recurring_billing.kid_id = OP.kid_id
AND CC.month_name = OP.billing_month
AND CC.billing_year = OP.billing_year
WHERE
ISNULL(tblkidsxclass.kxc_dropoutdate)
AND tblkidsxclass.pmt_option = 'Recurring'
AND tblclasses.cla_active = TRUE
AND recurring_billing.kid_id NOT IN
(
SELECT
kid_id
from
recurring_billing
where
billing_month = 'November'
and billing_year = '2020'
)
-- AND tblclasses.cla_EndDate >= NOW()
GROUP BY
recurring_billing.id
ORDER BY
recurring_billing.id ASC
Same query if enclosed in Parentheses will give me different results.
Parentheses are not required for a UNION statement. The following 2 union statements both work and yield the same results.
SELECT 1 UNION SELECT 2;
(SELECT 1) UNION (SELECT 2);

MySQL Union query: PASSING TEMP ClaimID field value to TEMP1 table ClaimID in one union query

CREATE DEFINER=`root`#`localhost` PROCEDURE `SP_DupAuditCriteria_1`()
BEGIN
set #RowNbr=concat(date_format(curdate(),'%Y%m%d'),'0000000');
select temp.* from
(SELECT c.*, concat(c.VendorID,a.VendorID) as MergeH200A, concat(a.VendorID,c.VendorID) as MergeH200B, 'New' as Record_Type, #RowNbr:= #RowNbr + 1 AS ClaimID
FROM tbldupaudit_currentitems AS c
inner join tbldupaudit_archiveitems a
on c.InvoiceID = a.InvoiceID
and c.GrossAmount = a.GrossAmount) as temp
inner join tbldupaudit_archiveitems b
on temp.InvoiceID = b.InvoiceID
and temp.GrossAmount = b.GrossAmount
and temp.VendorID = b.VendorID
and temp.VoucherID <> b.VoucherID
Union all
select temp1.* from
(SELECT f.*, concat(f.VendorID,d.VendorID) as MergeH200A, concat(d.VendorID,f.VendorID) as MergeH200B, 'ARCHIVE' as Record_Type, 1 AS ClaimID
FROM tbldupaudit_archiveitems AS f
inner join tbldupaudit_currentitems d
on f.InvoiceID = d.InvoiceID
and f.GrossAmount = d.GrossAmount) as temp1
inner join tbldupaudit_currentitems e
on temp1.InvoiceID = e.InvoiceID
and temp1.GrossAmount = e.GrossAmount
and temp1.VendorID = e.VendorID
and temp1.VoucherID <> e.VoucherID
order by InvoiceID, Record_Type DESC;
END
trying make unique ClaimID for each pair. I am able to generate sequential number for first half union all but same ClaimID not able to generate in other half Union all.
Please help me in how to create/generate one unique ID for matched items.
Thank you!]1
In the second select ( after the UNION ALL) you are not incrementing a var so if you want both value incrementeedc the try using a var also for the second
select temp.*
from (
SELECT c.*, concat(c.VendorID,a.VendorID) as MergeH200A, concat(a.VendorID,c.VendorID) as MergeH200B, 'New' as Record_Type
, #RowNbr:= #RowNbr + 1 AS ClaimID
FROM tbldupaudit_currentitems AS c
inner join tbldupaudit_archiveitems a on c.InvoiceID = a.InvoiceID
and c.GrossAmount = a.GrossAmount
) as temp
inner join tbldupaudit_archiveitems b on temp.InvoiceID = b.InvoiceID
and temp.GrossAmount = b.GrossAmount
and temp.VendorID = b.VendorID
and temp.VoucherID <> b.VoucherID
Union all
select temp1.*
from (
SELECT f.*, concat(f.VendorID,d.VendorID) as MergeH200A, concat(d.VendorID,f.VendorID) as MergeH200B, 'ARCHIVE' as Record_Type
, #RowNbr:= #RowNbr + 1 AS ClaimID
FROM tbldupaudit_archiveitems AS f
inner join tbldupaudit_currentitems d on f.InvoiceID = d.InvoiceID
and f.GrossAmount = d.GrossAmount
) as temp1
inner join tbldupaudit_currentitems e on temp1.InvoiceID = e.InvoiceID
and temp1.GrossAmount = e.GrossAmount
and temp1.VendorID = e.VendorID
and temp1.VoucherID <> e.VoucherID
order by InvoiceID, Record_Type DESC;
Modelling example - see fiddle :
SELECT CONCAT( 'prefix', LPAD( CASE #prev
WHEN #prev := InvoiceID
THEN #num
ELSE #num := #num + 1
END, 8, '0' ) ) ClaimID, InvoiceID, Amount, FromTable
FROM ( SELECT InvoiceID, Amount, 'CurrentItems' FromTable
FROM CurrentItems
UNION ALL
SELECT InvoiceID, Amount, 'ArchivedItems'
FROM ArchivedItems
WHERE EXISTS ( SELECT NULL
FROM CurrentItems
WHERE CurrentItems.InvoiceID = ArchivedItems.InvoiceID) ) unioned,
( SELECT #prev := 0, #num := 1000 ) variables
ORDER BY InvoiceID, FromTable DESC;

How to optimize for speed a sql multiple select with SUM

I have a really long select from my database with many joins. The problem is with counting SUM: without sum, select time is about 3s, but with SUM is about 15s.
Is it possible to optimize my select to obtain a shorter select time?
Here is my code:
SELECT
accomodation.id,
accomodation.aid,
accomodation.title_en,
accomodation.title_url_en,
accomodation.address,
accomodation.zip,
accomodation.stars,
accomodation.picture,
accomodation.valid_from,
accomodation.valid_to,
accomodation.latitude,
accomodation.longitude,
accomodation.city_id AS
accomodation_city_id,
db_cities.id AS city_id,
db_cities.title_en AS city,
db_cities.title_url AS city_url,
db_countries.title_en AS country_title,
db_countries.title_url_en AS country_url,
accomodation_type.class AS accomodation_type_class,
accomodation_review_value_total.value AS review_total,
MIN(accomodation_price.price) AS price_from,
accomodation_rooms.total_persons
FROM
(SELECT aid, MAX(info_date_add) AS max_info_date_add FROM accomodation GROUP BY aid) accomodation_max
INNER JOIN accomodation
ON
accomodation_max.aid = accomodation.aid AND
accomodation_max.max_info_date_add = accomodation.info_date_add
LEFT JOIN db_cities
ON (
db_cities.id = accomodation.city_id OR
(((acos(sin((db_cities.latitude*pi()/180)) * sin((accomodation.latitude*pi()/180)) + cos((db_cities.latitude*pi()/180)) * cos((accomodation.latitude*pi()/180)) * cos(((db_cities.longitude - accomodation.longitude)*pi()/180))))*180/pi())*60*1.1515*1.609344) < '20')
JOIN db_countries
ON db_countries.id = accomodation.country_id
LEFT JOIN accomodation_review_value_total
ON accomodation_review_value_total.accomodation_aid = accomodation.aid
LEFT JOIN accomodation_type_value
ON accomodation_type_value.accomodation_id = accomodation.id
LEFT JOIN accomodation_type
ON accomodation_type.id = accomodation_type_value.accomodation_type_id
JOIN accomodation_season
ON (
accomodation_season.accomodation_aid = accomodation.aid AND
( '2013-11-04' BETWEEN accomodation_season.start_date AND accomodation_season.end_date OR '2013-11-05' BETWEEN accomodation_season.start_date AND accomodation_season.end_date ) )
JOIN accomodation_price
ON
accomodation_price.accomodation_aid = accomodation.aid AND
accomodation_price.accomodation_price_type_id = '1' AND
accomodation_price.accomodation_price_cat_id = '1' AND
accomodation_price.price BETWEEN '20' AND '250' AND
accomodation_price.accomodation_season_id = accomodation_season.id
JOIN accomodation_theme_value
ON accomodation_theme_value.accomodation_id = accomodation.id
INNER JOIN
(SELECT
accomodation_id,
SUM(accomodation_rooms.rooms) AS total_rooms,
SUM(accomodation_rooms.beds * accomodation_rooms.rooms) AS total_persons
FROM accomodation_rooms
GROUP BY accomodation_id) accomodation_rooms
ON
accomodation_rooms.accomodation_id = accomodation.id AND
accomodation_rooms.total_persons >= '4'
WHERE
db_countries.title_url_en LIKE '%spain%' AND
db_cities.title_url LIKE '%barcelona%' AND
accomodation_type_value.accomodation_type_id IN (5,10) AND
total_rooms >= '2' AND
accomodation_theme_value.accomodation_theme_id IN (11,12,13) AND
accomodation.stars IN (3,4,5) AND
( accomodation_review_value_total.value >= '4.5' ) AND
db_cities.id = '2416'
GROUP BY accomodation.aid
ORDER BY
CASE
WHEN accomodation.valid_to>=NOW() AND accomodation.valid_from<=NOW() AND MIN(accomodation_price.price) IS NOT NULL THEN 0
WHEN NOW()>accomodation.valid_to AND accomodation.valid_to>'0000-00-00' AND MIN(accomodation_price.price) IS NOT NULL THEN 1
WHEN accomodation.valid_to>=NOW() AND accomodation.valid_from<=NOW() THEN 2
WHEN NOW()>accomodation.valid_to AND accomodation.valid_to>'0000-00-00' THEN 3
ELSE 4 END,
review_total DESC,
accomodation.title_en
LIMIT 10

MySQL Query Efficiency - Is there a better way?

I have a query that basically combines tables of actions and selects from them in chronological order while preserving pagination..
Is there a more efficient / better way to do this? The query takes 3 seconds. Not terrible.. but I think there is room for improvement and I will be using it alot..
Thanks!
SELECT
`newsletters_subscribers`.`email`,
`newsletters_subscribers`.`first_name`,
`newsletters_subscribers`.`last_name`,
`newsletters_subscribers`.`id` AS subscriber_id,
COUNT(DISTINCT newsletters_opens.id) AS opens,
COUNT(DISTINCT newsletters_clicks.id) AS clicks,
COUNT(DISTINCT newsletters_forwards.id) AS forwards
FROM `thebookrackqccom_newsletters_subscribers` newsletters_subscribers
LEFT JOIN
`thebookrackqccom_newsletters_opens` newsletters_opens
ON `newsletters_opens`.`subscriber_id` = `newsletters_subscribers`.`id`
AND newsletters_opens.newsletter_id = 1
LEFT JOIN
`thebookrackqccom_newsletters_clicks` newsletters_clicks
ON `newsletters_clicks`.`subscriber_id` = `newsletters_subscribers`.`id`
AND newsletters_clicks.newsletter_id = 1
LEFT JOIN
`thebookrackqccom_newsletters_forwards` newsletters_forwards
ON `newsletters_forwards`.`subscriber_id` = `newsletters_subscribers`.`id`
AND newsletters_forwards.newsletter_id = 1
WHERE
( newsletters_opens.id IS NOT NULL
OR newsletters_clicks.id IS NOT NULL
OR newsletters_forwards.id IS NOT NULL )
GROUP BY
`newsletters_subscribers`.`id`
ORDER BY
`newsletters_subscribers`.`email` ASC
LIMIT 25
What you need is indexes that the query can use. A compound index on (newsletter_id, subscribe_id) on each one of the three tables would help.
You can also rewrite the query like this:
SELECT
s.email,
s.first_name,
s.last_name,
s.id AS subscriber_id,
COALESCE(o.opens, 0) AS opens,
COALESCE(c.clicks, 0) AS clicks,
COALESCE(f.forwards, 0) AS forwards
FROM thebookrackqccom_newsletters_subscribers AS s
LEFT JOIN
( SELECT subscriber_id,
COUNT(*) AS opens
FROM thebookrackqccom_newsletters_opens
WHERE newsletters_opens.newsletter_id = 1
) AS o ON o.subscriber_id = s.id
LEFT JOIN
( SELECT subscriber_id,
COUNT(*) AS clicks
FROM thebookrackqccom_newsletters_clicks
WHERE newsletter_id = 1
) AS c ON c.subscriber_id = s.id
LEFT JOIN
( SELECT subscriber_id,
COUNT(*) AS forwards
FROM thebookrackqccom_newsletters_forwards
WHERE newsletter_id = 1
) AS f ON f.subscriber_id = s.id
WHERE ( o.subscriber_id IS NOT NULL
OR c.subscriber_id IS NOT NULL
OR f.subscriber_id IS NOT NULL )
ORDER BY
s.email ASC
LIMIT 25
Try this Query i hope you get a better execution time
QUERY
SELECT
`newsletters_subscribers`.`email`,
`newsletters_subscribers`.`first_name`,
`newsletters_subscribers`.`last_name`,
`newsletters_subscribers`.`id` AS subscriber_id,
#nopen := coalesce( N_OPEN.NOPENIDCOUNT, 000000 ) as opens,
#nclick := coalesce( N_CLICK.NCLICKIDCOUNT, 000000 ) as clicks,
#nfwd := coalesce( N_FWD.NFWDIDCOUNT, 000000 ) as forwards
FROM
(select #nopen := 0,#nclick := 0,#nfwd :=0) sqlvars,
`thebookrackqccom_newsletters_subscribers` AS newsletters_subscribers
LEFT JOIN (SELECT `newsletters_opens`.`subscriber_id`,
COUNT(newsletters_opens.id) AS NOPENIDCOUNT
FROM `thebookrackqccom_newsletters_opens` AS newsletters_opens
WHERE newsletters_opens.newsletter_id = 1) AS N_OPEN
ON N_OPEN.subscriber_id = `newsletters_subscribers`.`id`
LEFT JOIN (SELECT `newsletters_clicks`.`subscriber_id`,
COUNT(newsletters_clicks.id) AS NCLICKIDCOUNT
FROM `thebookrackqccom_newsletters_clicks` AS newsletters_clicks
WHERE newsletters_clicks.newsletter_id = 1) AS N_CLICK
ON N_CLICK.subscriber_id = `newsletters_subscribers`.`id`
LEFT JOIN (SELECT `newsletters_forwards`.`subscriber_id`,
COUNT(newsletters_forwards.id) AS NFWDIDCOUNT
FROM `thebookrackqccom_newsletters_forwards` AS newsletters_forwards
WHERE newsletters_forwards.newsletter_id = 1) AS N_FWD
ON N_FWD.subscriber_id = `newsletters_subscribers`.`id`
GROUP BY `newsletters_subscribers`.`id`
ORDER BY `newsletters_subscribers`.`email` ASC
LIMIT 25

MySQL query: Using UNION and getting row number as part of SELECT

I have a union query as follows:
(SELECT t.id, t.name, c.company AS owner, t.creation_date AS date, t.notes
FROM tool t, client c
WHERE t.id_customer = '15' AND t.trash_flag = '1')
UNION
(SELECT f.id, f.name, CONCAT(m.first_name, ' ', m.last_name) AS owner, f.date, f.notes
FROM file f, meta m
WHERE ((f.acl = 0) OR (f.acl = 1 AND '1' = TRUE) OR (f.acl = 2 AND f.id = '7')) AND f.id = '15' AND f.trash_flag = '1' AND m.user_id = f.id_user)
ORDER BY 'name' 'ASC' LIMIT 0,20
Everything works fine but I have two questions:
How do I add a column to the entire result set that gives the row number
Could I do this without using UNION e.g. an advanced join?
Thanks for your time MySQL gurus!
I can't test it righ now but from what I found, following might work:
Reference: Row Number Variable
SQL Statement
SELECT #rownum := #rownum + 1 rownum
, t.*
FROM (
(SELECT t.id
, t.name
, c.company AS owner
, t.creation_date AS date
, t.notes
FROM tool t
, client c
WHERE t.id_customer = '15'
AND t.trash_flag = '1'
) UNION (
SELECT f.id
, f.name
, CONCAT(m.first_name, ' ', m.last_name) AS owner
, f.date
, f.notes
FROM file f
, meta m
WHERE ((f.acl = 0) OR (f.acl = 1 AND '1' = TRUE) OR (f.acl = 2 AND f.id = '7')) AND f.id = '15' AND f.trash_flag = '1' AND m.user_id = f.id_user)
)
) t
, (SELECT #rownum := 0) r
ORDER BY
'name' ASC
LIMIT 0, 20