I want to make my report faster because is taking to long to load, i was wondering if there is a way to make multiple counts from just one select.
Example, make this select wish is not going to change for the counts
SELECT IDS, Fecha_Recarga, Banco_Recarga, Tipo, Status, RefVerif, MontoVerif, RecargaDuplicada FROM transaccionesrr WHERE Fecha_Recarga = '2017-02-07' AND Banco_Recarga = 'BANESCO' AND Tipo = 'RECARGA' AND Status = 'PROCESADA'
And based on the result of this select i want to make multiple counts like
Count (*) WHERE RefVerif = '1' AS RefVerif
Count (*) WHERE RefVerif = '1' AND MontoVerif = '0' AS MontoVerif
Count (*) WHERE RecargaDuplicada = '1' AS Duplicada
This is the Stored Procedure that i have right know
SELECT COUNT(*) AS RECARGAS,
(SELECT COUNT(*) FROM transaccionesrr WHERE Tipo = 'RECARGA' AND Status = 'PROCESADA' AND Fecha_Recarga BETWEEN PRM_Fecha_Desde AND PRM_Fecha_Hasta AND Banco_Recarga = PRM_Banco AND RefVerif = '1') AS VERIFICADAS,
(SELECT COUNT(*) FROM transaccionesrr WHERE Tipo = 'RECARGA' AND Status = 'PROCESADA' AND Fecha_Recarga BETWEEN PRM_Fecha_Desde AND PRM_Fecha_Hasta AND Banco_Recarga = PRM_Banco AND RefVerif = '0') AS NOVERIFICADAS,
(SELECT COUNT(*) FROM transaccionesrr WHERE Tipo = 'RECARGA' AND Status = 'PROCESADA' AND Fecha_Recarga BETWEEN PRM_Fecha_Desde AND PRM_Fecha_Hasta AND Banco_Recarga = PRM_Banco AND RefVerif = '1' AND MontoVerif = '0') AS MONTOVERIF,
(SELECT COUNT(*) FROM transaccionesrr WHERE Tipo = 'RECARGA' AND Status = 'PROCESADA' AND Fecha_Recarga BETWEEN PRM_Fecha_Desde AND PRM_Fecha_Hasta AND Banco_Recarga = PRM_Banco AND RecargaDuplicada = '1') AS DUPLICADAS
FROM transaccionesrr WHERE Tipo = 'RECARGA' AND Status = 'PROCESADA' AND Fecha_Recarga BETWEEN PRM_Fecha_Desde AND PRM_Fecha_Hasta AND Banco_Recarga = PRM_Banco ;
Im trying to do this because i think it will be faster if you think there is a better way i will be appreciated.
I have been trying to make a solution for days but i don't find any
Use conditional aggregation:
SELECT COUNT(*) AS RECARGAS,
SUM(RefVerif = '1') AS VERIFICADAS,
SUM(RefVerif = '0') AS NOVERIFICADAS,
SUM(RefVerif = '1' AND MontoVerif = '0') AS MONTOVERIF,
SUM(RecargaDuplicada = '1') AS DUPLICADAS
FROM transaccionesrr
WHERE Tipo = 'RECARGA' AND Status = 'PROCESADA' AND
Fecha_Recarga BETWEEN PRM_Fecha_Desde AND PRM_Fecha_Hasta AND
Banco_Recarga = PRM_Banco ;
Related
I need the following sql query into laravel query or how can I run into laravel as it is. thanks
SELECT t.*
FROM (SELECT client_id,product_name, max(real_date) AS max_date
FROM api_hilbertis.transactions
WHERE active = 1 AND real_date <= '2019-03-01'
GROUP BY client_id, product_name) AS m
INNER JOIN api_hilbertis.transactions AS t
ON t.client_id = m.client_id
AND t.product_name = m.product_name
AND t.real_date = m.max_date
AND active = 1
ORDER BY real_date DESC;
You can use laravel raw queries.
Example HERE
So for your case it we could write something like:
$results = DB::select( DB::raw("
SELECT t.*
FROM (SELECT client_id,product_name, max(real_date) AS max_date
FROM api_hilbertis.transactions
WHERE active = 1 AND real_date <= '2019-03-01'
GROUP BY client_id, product_name) AS m
INNER JOIN api_hilbertis.transactions AS t
ON t.client_id = m.client_id
AND t.product_name = m.product_name
AND t.real_date = m.max_date
AND active = 1
ORDER BY real_date DESC"
));
EDIT: example with variables:
$someVariable = $request->input('some_variable');
$results = DB::select( DB::raw("SELECT * FROM some_table WHERE some_col = :somevariable"),
['somevariable' => $someVariable,]
);
SELECT ST.Id,
ST.Label,
ST.Asset,
CASE
WHEN ST.RFID = '' THEN 'NULL'
ELSE ST.RFID
END AS RFID,
CASE
WHEN ST.Type = 'O' THEN 'Odometer'
ELSE 'Engine Hours'
END AS AccumulatorType,
ST.AppId,
ST.Timestamp,
ST.Accumulator,
CASE
WHEN ST.Flag = 0 THEN 'Disabled'
WHEN ST.Flag = 1 THEN 'Active'
WHEN ST.Flag = 3 THEN 'Rented'
WHEN ST.Flag = 4 THEN 'Bypass'
WHEN ST.Flag = 5 THEN 'Tanker'
END AS TYPE,
(SELECT COUNT(*)
FROM sync
WHERE RowId = ST.Id
AND DefinitionId = 1
AND Status = 1) AS Updated,
(SELECT COUNT(*)
FROM sync
WHERE RowId = ST.Id
AND DefinitionId = 1
AND Status = 0) AS Remaining
FROM SecondaryTags AS ST
WHERE AppId = #AppId
Why do you want to rewrite the logic? Because you have filtering in the outer query, the subquery is likely to be the most performant method for the calculation.
You can speed the subquery by being sure that you have the write indexes. In this case, you want an index on sync(RowId, DefinitionId, StatusId):
create index idx_sync_rowid_definitionid_statusid
on sync(RowId, DefinitionId, StatusId)
You can rewrite the query as:
select . . .,
s.updated, s.remaining
from SecondaryTags st join
(select rowid, sum(status = 1) as updated, sum(status = 0) as remaining
from sync s
where s.definitionId = 1
group by s.rowid
) s
on s.rowid = st.id
where st.AppId = #AppId;
From a performance perspective, though, I think the index is a better idea.
select st.*
, s.updated
, s.remaining
from SecondaryTags st
join (select rowid
, sum(status = 1) as updated
, sum(status = 0) as remaining
from sync s
where s.definitionId = 1
group
by s.rowid
) s
on s.rowid = st.id
where st.AppId = 2;
query taking 1 minute to fetch results
SELECT
`jp`.`id`,
`jp`.`title` AS game_title,
`jp`.`game_type`,
`jp`.`state_abb` AS game_state,
`jp`.`location` AS game_city,
`jp`.`zipcode` AS game_zipcode,
`jp`.`modified_on`,
`jp`.`posted_on`,
`jp`.`game_referal_amount`,
`jp`.`games_referal_amount_type`,
`jp`.`status`,
`jp`.`is_flaged`,
`u`.`id` AS employer_id,
`u`.`email` AS employer_email,
`u`.`name` AS employer_name,
`jf`.`name` AS game_function,
`jp`.`game_freeze_status`,
`jp`.`game_statistics`,
`jp`.`ats_value`,
`jp`.`integration_id`,
`u`.`account_manager_id`,
`jp`.`model_game`,
`jp`.`group_id`,
(CASE
WHEN jp.group_id != '0' THEN gm.group_name
ELSE 'NA'
END) AS group_name,
`jp`.`priority_game`,
(CASE
WHEN jp.country != 'US' THEN jp.country_name
ELSE ''
END) AS game_country,
IFNULL((CASE
WHEN
`jp`.`account_manager_id` IS NULL
OR `jp`.`account_manager_id` = 0
THEN
(SELECT
(CASE
WHEN
account_manager_id IS NULL
OR account_manager_id = 0
THEN
`u`.`account_manager_id`
ELSE account_manager_id
END) AS account_manager_id
FROM
user_user
WHERE
id = (SELECT
user_id
FROM
game_user_assigned
WHERE
game_id = `jp`.`id`
LIMIT 1))
ELSE `jp`.`account_manager_id`
END),
`u`.`account_manager_id`) AS acc,
(SELECT
COUNT(recach_limit_id)
FROM
recach_limit
WHERE
recach_limit = '1'
AND recach_limit_game_id = rpr.recach_limit_game_id) AS somewhatgame,
(SELECT
COUNT(recach_limit_id)
FROM
recach_limit
WHERE
recach_limit = '2'
AND recach_limit_game_id = rpr.recach_limit_game_id) AS verygamecommitted,
(SELECT
COUNT(recach_limit_id)
FROM
recach_limit
WHERE
recach_limit = '3'
AND recach_limit_game_id = rpr.recach_limit_game_id) AS notgame,
(SELECT
COUNT(joa.id) AS applicationcount
FROM
game_refer_to_member jrmm
INNER JOIN
game_refer jrr ON jrr.id = jrmm.rid
INNER JOIN
game_applied joa ON jrmm.id = joa.referred_by
WHERE
jrmm.STATUS = '1'
AND jrr.referby_user_id IN (SELECT
ab_testing_user_id
FROM
ab_testing)
AND joa.game_post_id = rpr.recach_limit_game_id
AND (rpr.recach_limit = 1
OR rpr.recach_limit = 2)) AS gamecount
FROM
(`game_post` AS jp)
JOIN
`user_info` AS u ON `jp`.`user_user_id` = `u`.`id`
JOIN
`game_functional` jf ON `jp`.`game_functional_id` = `jf`.`id`
LEFT JOIN
`group_musesm` gm ON `gm`.`group_id` = `jp`.`group_id`
LEFT JOIN
`recach_limit` rpr ON `jp`.`id` = `rpr`.`recach_limit_game_id`
WHERE
`jp`.`status` != '3'
GROUP BY `jp`.`id`
ORDER BY `posted_on` DESC
LIMIT 10
I would first suggest not nesting select statements because this will cause an n^x performance hit on every xth level and I see at least 3 levels of selects inside this query.
Add index
INDEX(status, posted_on)
Move LIMIT inside
Then, instead of saying
FROM (`game_post` AS jp)
say
FROM ( SELECT id FROM game_post
WHERE status != 3
ORDER BY posted_on DESC
LIMIT 10 ) AS ids
JOIN game_post AS jp USING(id)
(I am assuming that the PK of jp is (id)?)
That should efficiently use the new index to get the 10 ids needed. Then it will reach back into game_post to get the other columns.
LEFT
Also, don't say LEFT unless you need it. It costs something to generate NULLs that you may not be needing.
Is GROUP BY necessary?
If you remove the GROUP BY, does it show dup ids? The above changes may have eliminated the need.
IN(SELECT) may optimize poorly
Change
AND jrr.referby_user_id IN ( SELECT ab_testing_user_id
FROM ab_testing )
to
AND EXISTS ( SELECT * FROM ab_testing
WHERE ab_testing_user_id = jrr.referby_user_id )
(This change may or may not help, depending on the version you are running.)
More
Please provide EXPLAIN SELECT if you need further assistance.
I have a table with the following fields:
SELECT `sms_id`,
`u_id`,
`sender_id`,
`mobile_no`,
`message`,
`campaign_name`,
`status`,
`request_id`,
`route_id`,
`totalnumber`,
`msgcreadit`,
`date1`,
`deductbal`,
`submited`
FROM `send_sms`
WHERE 1
I want to select u_id whose status ="pending", but I want the latest pending status according to the [date1] date field and I also want the count of individual u_ids with status ="pending".
How can I do it?
In MySQL you can do:
SELECT s.*
FROM `send_sms` s
WHERE s.status = 'pending' AND
s.date1 = (SELECT MAX(s2.date1) FROM send_sms s2 WHERE s2.u_id = s.u_id and s2.status = 'pending');
Just another approach:
SELECT s.*
FROM `send_sms` s
LEFT JOIN `send_sms` s2
ON s.date1 < s2.date1
AND s2.u_id = s.u_id
AND s2.status = 'pending'
WHERE s.status = 'pending'
AND s2.status IS NULL
I have a problem with a MySQL Query:
I have two tables:
- clustercategories
- domains
Now I have a SQL Query which lists all Domains of a specific category with category name - this is my Query:
SELECT domains.*, clustercategories.clustercategoryname
FROM (domains, clustercategories)
WHERE ((clustercategories.id = 3 AND (domains.cluster1id = 3 OR domains.cluster2id = 3))
OR (clustercategories.id = 10 AND (domains.cluster1id = 10 OR domains.cluster2id = 10)))
AND domains.status = '1'
GROUP BY domains.name
ORDER BY domains.name
The Problem is now, that I also have a third table "subpages" where I want to count all entries of a specific domain with status = '1' and I don't know how to modify my query to work - I have tried this query, but I do not get any results:
SELECT domains.*, clustercategories.clustercategoryname
FROM (domains, clustercategories)
WHERE ((clustercategories.id = 3 AND (domains.cluster1id = 3 OR domains.cluster2id = 3) AND (SELECT COUNT(*) AS total FROM subpages WHERE subpages.domainid = domains.id AND subpages.status = '1'))
OR (clustercategories.id = 10 AND (domains.cluster1id = 10 OR domains.cluster2id = 10) AND (SELECT COUNT(*) AS total FROM subpages WHERE subpages.domainid = domains.id AND subpages.status = '1')))
AND domains.status = '1'
GROUP BY domains.name
ORDER BY domains.name
Has anyone any ideas?
I think that you'll want to put your subquery into your projection, like this:
SELECT domains.*, clustercategories.clustercategoryname,
(SELECT COUNT(*) FROM subpages WHERE subpages.domainid = domains.id AND subpages.status = '1') AS total
FROM domains, clustercategories
WHERE ((clustercategories.id = 3 AND (domains.cluster1id = 3 OR domains.cluster2id = 3))
OR (clustercategories.id = 10 AND (domains.cluster1id = 10 OR domains.cluster2id = 10)))
AND domains.status = '1'
GROUP BY domains.name
ORDER BY domains.name
It looks to me your first query can be rewritten like this
SELECT d.*
, cc.clustercategoryname
FROM domains d
INNER JOIN clustercategories cc
ON cc.id = d.cluster1id
OR cc.id = d.cluster2id
WHERE cc.id IN (3, 10)
AND d.status = '1'
GROUP BY
d.name
ORDER BY
d.name
thus adding the count of subpages can be done like this
SELECT d.*
, cc.clustercategoryname
, sp.total
FROM domains d
INNER JOIN clustercategories cc
ON cc.id = d.cluster1id
OR cc.id = d.cluster2id
LEFT OUTER JOIN (
SELECT COUNT(*) AS total
, domainid
FROM subpages
WHERE subpages.status = '1'
GROUP BY
domainid
) sp ON sp.domainid = d.domainid
WHERE cc.id IN (3, 10)
AND d.status = '1'
GROUP BY
d.name
ORDER BY
d.name