Query is taking too much time after adding index - mysql

Query is taking too much time after adding index.
SELECT bc.billabletreatmentsetup_id, bs.name, IFNULL(bc.charges_for,'OPD')
as charges_for_vals, bc.nc_applicable, bc.unit_value, bc.taxtype_id, bc.id, bc.amount, bc.effective_date
FROM billabletreatmentcharges bc, billabletreatmentsetups bs
WHERE bs.id = bc.billabletreatmentsetup_id
AND bs.status='Active'
AND bs.branch_id = '9197651b-e2b9-1924-b931-54f13cfc31c0'
AND bs.deleted=0
AND ( bc.billabletreatmentsetup_id, bc.effective_date, bc.date_modified, IFNULL(bc.charges_for,'OPD') )
IN (
SELECT billabletreatmentsetup_id, max( effective_date ) , max( date_modified ), IFNULL(charges_for,'OPD')
FROM billabletreatmentcharges
WHERE effective_date <= '2015-03-12'
AND insprovider_id IS NULL GROUP BY billabletreatmentsetup_id, charges_for
)
AND bc.insprovider_id IS NULL ORDER BY bs.name, bc.charges_for ASC

Related

The rownum and alignment order do not work as desired

I don't want to be an order by channel ID.
All I want is order by book_date for the entire channel.
SELECT * FROM
(
SELECT CAST(#rownum := #rownum +1 AS signed integer) AS row_cnt
, id /* index */
, CASE WHEN 0 < (SELECT count(*) FROM cmsDB.g_room_type WHERE name = t1.room_type AND chanel_mgt_id = t1.chanel_mgt_id) THEN '정상' ELSE '비매칭' END AS status
, DATE_FORMAT(book_date,'%Y-%m-%d') AS book_date
, room_type
, (SELECT info.room_name FROM cmsDB.g_room_info info, cmsDB.g_room_type tp WHERE info.id = tp.room_info_id AND tp.name = t1.room_type AND tp.chanel_mgt_id = t1.chanel_mgt_id GROUP BY info.room_name) AS room_name
, DATEDIFF(check_out_date,check_in_date) AS night_cnt
, check_in_date
, check_out_date
, room_num
, book_name
, phone_num
, book_num
, reg_book_num
, deposit_price
, book_status
, client_status
, sub_chanel_sort
, t2.companyNm AS company_name
, t1.remarks
, t1.night_date
, t1.reg_status
, chanel_mgt_id
, (SELECT sort.name FROM cmsDB.g_chanel_sort sort WHERE sort.id = t2.chanelSortId) AS chanelName
FROM
cmsDB.e_cl_book_themoum t1
LEFT JOIN (
SELECT
cm.id AS chanelMgtId
, ci.name AS companyNm, cm.chanel_sort_id AS chanelSortId
FROM cmsDB.g_chanel_mgt cm, cmsDB.g_company_info ci
WHERE cm.company_info_id = ci.id) t2
ON t2.chanelMgtId = t1.chanel_mgt_id
, (SELECT #rownum := 0) r
WHERE 1=1 AND t1.chanel_mgt_id in ( 49 , 50 , 56 , 69 , 70 , 71 )
ORDER BY t1.book_date asc
) tbl ORDER BY 1 desc LIMIT 0,10 ;
If you do this, the results will be...
https://i.stack.imgur.com/8B6Qi.png
This is the result.
But the result I want is the date order for the entire channel_id.
Instead of order by 1 based on column position in select clause (first column on select )
You should use an explicit order by using column name
ORDER BY book_date desc LIMIT 0,10 ;
or
ORDER BY chanel_mgt_id, book_date desc LIMIT 0,10 ;
if you want also the row_cnt then add the column name in the position you need
ORDER BY chanel_mgt_id, book_date, row_cnt desc LIMIT 0,10 ;

MySQL - query to return NULL

I have the following code:
SELECT q25, (
(
AVG( q1 ) + AVG( q2 ) + AVG( q3 ) ) /3 ) AS Overall
FROM t_results
WHERE brand = 'XYZ'
AND DATE = 'MAY2012'
GROUP BY q25
ORDER BY Overall
DESC LIMIT 1
If there is no data found by the query phpmyadmin returns the following message (which is quite correct):
MySQL returned an empty result set (i.e. zero rows). ( Query took 0.0178 sec )
However, what I'd like is to actually return a NULL value, is this possible? I appreciate this might not be best practise but I'm working with inherited code and this might be the simplist and quickest route to a solution.
Thanks as always,
H.
Create a table with exactly one row. Then you can use left join to achieve the desired NULL result.
CREATE TABLE dummy (d TINYINT NOT NULL);
INSERT INTO dummy SET d = 1;
SELECT q25,
( ( AVG( q1 ) + AVG( q2 ) + AVG( q3 ) ) /3 ) AS Overall
FROM dummy LEFT JOIN t_results
ON brand = 'XYZ'
AND DATE = 'MAY2012'
GROUP BY q25
ORDER BY Overall DESC
LIMIT 1
You can also replace the dummy table with a subquery:
SELECT q25,
( ( AVG( q1 ) + AVG( q2 ) + AVG( q3 ) ) /3 ) AS Overall
FROM (SELECT 1) AS dummy LEFT JOIN t_results
ON brand = 'XYZ'
AND DATE = 'MAY2012'
GROUP BY q25
ORDER BY Overall DESC
LIMIT 1
Tested this via sqlfiddle, where you can also experiment with alternatives.
The conditions selecting the result, which used to be in the WHERE clause, now have to go into the ON clause. Otherwise the left join would produce non-NULL rows which would be removed by the WHERE, instead of generating a single NULL row if no matching row could be found. If there were no WHERE conditions in the original query, ON 1 could be used to express any row matches.
You can use a UNION combined with a LIMIT to supply the NULL values:
(SELECT q25,
(AVG(q1) + AVG(q2) + AVG(q3))/3 AS Overall
FROM t_results
WHERE brand = 'XYZ'
AND DATE = 'MAY2012'
GROUP BY q25
ORDER BY Overall DESC
LIMIT 1
)
UNION ALL
(SELECT NULL, NULL)
LIMIT 1;
This only works when you know that the first query will never yield more than one result, though. Which is the case here, so this might be the best solution for you, but the approach given in my other answer is more general.
There is a fiddle for this to experiment with.
The coalesce() function can be used to return the first non-null value from a number of comma separated columns or strings. The values/columns are evaluated left to right, so if you want to pop a string into the arguments that isn't null, make sure you place it to the right of the columns that you are testing against.
select
coalesce(
(
SELECT
q25
FROM
t_results
WHERE
brand = 'XYZ'
AND DATE = 'MAY2012'
GROUP BY
q25
LIMIT 1
), 'null') as q25,
coalesce(
(
SELECT
((AVG( q1 ) + AVG( q2 ) + AVG( q3 ) ) /3 ) AS Overall
FROM t_results
WHERE
brand = 'XYZ'
AND DATE = 'MAY2012'
LIMIT 1
), 'null') as Overall
from
t_results
group by
1, 2;
If you don't have data that matches your where clause, this will return null, null as a row.

How to merge the result of this 2 queries in mysql server

I am actually stuck in merging the result of this two queries:
first query:
SELECT c.code, c.name, pc.sku, pc.cat_code, pp.title
FROM `cat_parent` cp, cat c, prod_cat pc, products pp
WHERE c.code = cp.cat_code
AND cp.cat_code = pc.cat_code
AND pp.sku = pc.sku
AND cp.parent_code = 01110
AND hide =0
The result I get is:
Second query:
SELECT `sku` , `update_date` , `description` , count( * ) AS total_sold
FROM `orderline`
WHERE `update_date` >= ( DATE_ADD(CURDATE( ) , INTERVAL -14 DAY ) )
AND `update_date` <= ( DATE_ADD(CURDATE( ) , INTERVAL -7 DAY ) )
GROUP BY left( sku, 7 )
ORDER BY total_sold DESC
The result:
The question I want to ask that how can I get the result by filtering the sku available in both tables.
Just bit confused on that part....any ideas will be appreciated.
This is only part of the data. there is heaps of data. Yes, I want to merge the both tables and want to find the common sku available in both tables.
My expected result will be sku, title, total sold.
Thanks, anyway I managed to get around to get the result.
My final query:
SELECT * FROM (
SELECT sku , update_date , description FROM orderline WHERE
update_date >= '2012-03-06' AND update_date <= '2012-03-07' )g
JOIN (
SELECT c.code, c.name, pc.sku, pc.cat_code FROM cat_parent cp, cat
c, prod_cat pc, products pp WHERE c.code = cp.cat_code AND cp.cat_code
= pc.cat_code AND pp.sku = pc.sku AND cp.parent_code =01110 AND hide =0 )p ON left( g.sku, 7 ) = left( p.sku, 7 )
Something like this -
SELECT
`c`.`code`, `c`.`name`, `pc`.`sku`, `pc`.`cat_code`, `pp.title`,
`ol`.`sku`, `ol`.`update_date`, `ol`.`description`, COUNT(*) AS `total_sold`
FROM `cat_parent` `cp`
INNER JOIN `cat` `c`
ON `c`.`code` = `cp`.`cat_code`
INNER JOIN `prod_cat` `pc`
ON `cp`.`cat_code` = `pc`.`cat_code`
INNER JOIN `products` `pp`
ON `pp`.`sku` = `pc`.`sku`
INNER JOIN `orderline` `ol`
ON LEFT(`pc`.`sku`, 7) = LEFT(`ol`.`sku`, 7)
WHERE `cp`.`parent_code` = 01110
AND `hide` = 0
AND `ol`.`update_date` >= ( DATE_ADD(CURDATE( ) , INTERVAL -14 DAY ) )
AND `ol`.`update_date` <= ( DATE_ADD(CURDATE( ) , INTERVAL -7 DAY ) )
GROUP BY left( `ol`.`sku`, 7 )
ORDER BY `total_sold` DESC

mysql date-format returns null

I have the following SQL query. It returns NULL for the 'invoice_date'.
SELECT * , fk_uid AS userId, fk_ivid AS invoice_uid, (
SELECT company
FROM tbl_users
WHERE pk_uid = userId
) AS invoice_customer, (
SELECT DATE_FORMAT( '%d/%m/%y', purchased ) AS invoice_date
FROM _invoices
WHERE invoice_uid = invoice_uid
LIMIT 1
) AS invoice_date
FROM tbl_statement_items
WHERE statement_generated = '1'
AND fk_statementId = '1'
LIMIT 0 , 30
Any help would be appriciated.
Thanks
You have inverted date_format parameters order.

Why can i sort an inline SELECT value but not use it in a WHERE clause?

I have this small SQL query.
SELECT a.`id` , a.`title` , a.`date` ,
(
SELECT MAX( grade )
FROM tests
WHERE userid = 41
AND presid = a.`id`
) AS grade
FROM `presentations` a
WHERE a.`visible` = 1
AND `grade` >= 5
ORDER BY `grade` DESC
This gives me the error
1054 - Unknown column 'grade' in 'where clause'
But if i remove the 2nd last line, it works fine. I have tried to do AND a.grade and even give the tests table a name and append that name to grade but still no luck.
How can I use this inline query in a WHERE clause?
I have found that this works, but is it the only way?
SELECT a.`id` , a.`title` , a.`date` ,
(
SELECT MAX( grade )
FROM tests
WHERE userid = 41
AND presid = a.`id`
) AS grade
FROM `presentations` a
WHERE a.`visible` = 1
AND (
SELECT MAX( grade )
FROM tests
WHERE userid = 41
AND presid = a.`id`
) >= 5
ORDER BY `grade` DESC
Sql statements are somewhat evaluated in the following order:
FROM
WHERE
SELECT
GROUP
HAVING
ORDER
So things you define in the SELECT-clause are not available in the WHERE-clause. You would need to put that constraint into a HAVING-clause:
SELECT a.`id` , a.`title` , a.`date` ,
(
SELECT MAX( grade )
FROM tests
WHERE userid = 41
AND presid = a.`id`
) AS grade
FROM `presentations` a
WHERE a.`visible` = 1
HAVING `grade` >= 5
ORDER BY `grade` DESC
SELECT a.`id` , a.`title` , a.`date` ,
(
SELECT MAX( grade )
FROM tests
WHERE userid = 41
AND presid = a.`id`
) AS grade
FROM `presentations` a
WHERE a.`visible` = 1
HAVING `grade` >= 5
ORDER BY
`grade` DESC