how to convert this OR operator to case statement - mysql

i have the below query, i want to know about the case statement by changing the below type of operator.
SELECT t_product.a_productid,
t_product.a_mpactive,
t_product.a_active,
trim(substring_index(a_reference,'_',-1)) as a_reference,
t_product.a_shopid,
t_productlang.a_name,
t_deactivatedproduct.a_reason
FROM t_deactivatedproduct
inner join
(SELECT max(a_deactivatedproductid) as a_deactivatedproductid
FROM t_deactivatedproduct
GROUP by t_deactivatedproduct.a_productid) as a on a.a_deactivatedproductid = t_deactivatedproduct.a_deactivatedproductid
INNER JOIN t_product ON t_product.a_productid = t_deactivatedproduct.a_productid
INNER JOIN t_productlang ON t_product.a_productid = t_productlang.a_productid AND t_product.a_shopid IN(2,3,5,6,7,10,8,15,12,16,17,26,27,28)
WHERE t_product.a_ispublished = 1
AND ((t_product.a_active = 1 AND t_product.a_mpactive = 0)
OR (t_product.a_active = 0 AND t_product.a_mpactive = 1)
OR (t_product.a_active = 0 AND t_product.a_mpactive = 0))
ORDER BY t_deactivatedproduct.a_deactivatedproductid DESC limit 700;

CASE is probably not the best pick to express such boolean logic. MySQL, however, understands tuple equality, so you could rewrite this:
AND (
(t_product.a_active = 1 AND t_product.a_mpactive = 0)
OR (t_product.a_active = 0 AND t_product.a_mpactive = 1)
OR (t_product.a_active = 0 AND t_product.a_mpactive = 0)
)
As:
AND (t_product.a_active, t_product.a_mpactive) in ( (1, 0), (0, 1), (0, 0) )
That will make the query neater, but not necessarily faster. Under the hood, the optimizer rewrites the query and both expressions might be ultimately interpreted similarly.
If we were to phrase this with CASE, we would have to wrap it somehow, to make it look like a predicate. Something like:
AND 1 = CASE
WHEN t_product.a_active = 1 AND t_product.a_mpactive = 0 THEN 1
WHEN t_product.a_active = 0 AND t_product.a_mpactive = 1 THEN 1
WHEN t_product.a_active = 0 AND t_product.a_mpactive = 0 THEN 1
END
... And, for what it's worth... If both columns always store non-null boolean values (0/1), then the condition is simpler phrased as a negation:
WHERE NOT (t_product.a_active = 1 AND t_product.a_mpactive = 1)
Or:
WHERE (t_product.a_active, t_product.a_mpactive) not in ( (1, 1) )

Related

Converting MySQL Queries to SQL Server

Can anyone please help converting the MySQL query below to SQL Server.
The 'DATE_FORMAT' and the LIMIT:limit are the problem.
SELECT
DATE_FORMAT(e.eventTime, '%m/%d/%Y %h:%i:%s %p') eventTime,
e.displayPath,
SUBSTRING_INDEX(source, '/alm:', -1) name,
e.eventType,
CASE WHEN e.priority = 0 THEN 'Diagnostic' WHEN e.priority = 1 THEN 'Low' WHEN e.priority = 2 THEN 'Medium' WHEN e.priority = 3 THEN 'High' WHEN e.priority = 4 THEN 'Critical' ELSE '' END priority,
COALESCE(COALESCE(COALESCE(d.intvalue, d.floatvalue), d.strvalue), '') eventValue,
COALESCE(ack.strvalue, '') ackUser
FROM
alarm_events e
LEFT JOIN alarm_event_data d ON d.id = e.id AND d.propname = 'eventValue'
LEFT JOIN alarm_event_data ack ON ack.id = e.id AND ack.propname = 'ackUser'
WHERE
eventtime BETWEEN :startDate AND :endDate AND priority BETWEEN :minPriority AND :maxPriority AND
((:active AND e.eventtype = 0) OR (:clear AND e.eventtype = 1) OR (:ack AND e.eventtype = 2))
ORDER BY
e.eventTime DESC
LIMIT :limit
Variables in SQL use an # instead of the : so you would need to adjust for that and populate your variables from the application.
Instead of the LIMIT parameter, you'd begin the query with a SELECT TOP #limit
The SUBSTRING_INDEX function needs to be adjusted to a standard SUBSTRING and PATINDEX function.
You would need to use the FORMAT() instead of DATE_FORMAT() function ().
As mentioned in the comments, using additional COALESCE() functions in SQL Server is unnecessary.
So the final query would look something like this (with variables to be set by your calling program):
SELECT TOP (#limit)
FORMAT(e.eventTime, 'M/d/yy hh:mm:ss tt') eventTime,
e.displayPath,
SUBSTRING(source, patindex(source,'/alm:'),len(source)) name,
e.eventType,
CASE WHEN e.priority = 0 THEN 'Diagnostic' WHEN e.priority = 1 THEN 'Low' WHEN e.priority = 2 THEN 'Medium' WHEN e.priority = 3 THEN 'High' WHEN e.priority = 4 THEN 'Critical' ELSE '' END priority,
COALESCE(d.intvalue, d.floatvalue, d.strvalue, '') eventValue,
COALESCE(ack.strvalue, '') ackUser
FROM
alarm_events e
LEFT JOIN alarm_event_data d ON d.id = e.id AND d.propname = 'eventValue'
LEFT JOIN alarm_event_data ack ON ack.id = e.id AND ack.propname = 'ackUser'
WHERE
eventtime BETWEEN #startDate AND #endDate AND priority BETWEEN #minPriority AND #maxPriority AND
((#active AND e.eventtype = 0) OR (#clear AND e.eventtype = 1) OR (#ack AND e.eventtype = 2))
ORDER BY
e.eventTime DESC

MYSQL Group by DATA NOT individually

This is My Data:
I want select data Like This ▼
I try select that in group by but is not individually data show.
and this is my code
select
date_format((select receive_contract_datetime from worklist_info where id = worklist_id), '%y.%m.%d') as receive_datetime,
(select trade_name from trade_info where id = (select worklist_trade_id from worklist_info where id = worklist_id)) as trade_name,
(select staff_name from staff_info where id =
(select account_staff_id from account_info where id =
(select worklist_account_id from worklist_info where id = worklist_id))) as worklist_writer,
date_format((select worklist_output_plan_date from worklist_info where id = worklist_id), '%y.%m.%d') as output_plan_date,
(select worklist_project_name from worklist_info where id = worklist_id) as prj_name,
worklist_sub_process_id,
count(worklist_sub_process_id),
sum(worklist_sub_state),
-- (sum(worklist_sub_process_id = 1)*2) as laser_count, worklist_sub_state
-- sum(worklist_sub_process_id = 1) as laser_count,
-- if(sum(worklist_sub_process_id = 1) > 0,count(IF(worklist_sub_process_id = 1, if(worklist_sub_state = 0,1,null), null)),-1) as laser_wait,
-- if(sum(worklist_sub_process_id = 1) > 0,count(IF(worklist_sub_process_id = 1, if(worklist_sub_state = 1,1,null), null)),-1) as laser_run,
-- if(sum(worklist_sub_process_id = 1) > 0,count(IF(worklist_sub_process_id = 1, if(worklist_sub_state = 2,1,null), null)),-1) as laser_end,
(select worklist_comment from worklist_info where id = worklist_id) as worklist_comment,
(select worklist_lot from worklist_info where id = worklist_id) as lot_number
from worklist_info_sub group by worklist_id,worklist_sub_process_id;
You seem to pivot your dataset. For this, you can use conditional aggregation:
select col_master_id,
sum(col_semi_id = 1) as col_semi_1_count,
sum(case when col_semi_id = 1 then col_state else 0 end) as col_semi_1_state,
sum(col_semi_id = 2) as col_semi_2_count,
sum(case when col_semi_id = 2 then col_state else 0 end) as col_semi_2_state,
sum(col_semi_id = 3) as col_semi_3_count,
sum(case when col_semi_id = 3 then col_state else 0 end) as col_semi_3_state,
from mytable
group by col_master_id
I don't see how your query relates to your data. This answer is based on your sample data and desired results, not on your query.

Getting the result from the first matched condition and not consider result from the next matched condition

I have a requirement to get the result from the first matched condition and if it finds result in that level then return from there or go to Next level to
find the result .
Any help appreciated.
This is a prioritization query (with ties). One method uses dense_rank():
select rsc.*
from (select rsc.*,
dense_rank() over (order by case when rsc.entityId = :accountId and rsc.entityTypeCode = 'A' then 1
when rsc.entityId = :companyId and rsc.entityTypeCode = 'C' then 2
when rsc.entityId = :issuerId and rsc.entityTypeCode = 'I' then 3
else 4
end) as seqnum
from CurrentRuleSetContents rsc
where (rsc.entityId = :accountId and rsc.entityTypeCode = 'A') or
(rsc.entityId = :companyId and rsc.entityTypeCode = 'C') or
(rsc.entityId = :issuerId and rsc.entityTypeCode = 'I') or
(rsc.industryCode = :industryCode)
) rsc
where seqnum = 1;

Add results of a query

I have this query:
select
sum(if(idcasa = 254, gcasa, 0)) as casa,
sum(if(idvisitante = 254, gvisitante, 0)) as visitante
from partido
where idcasa = 254 or idvisitante = 254 and idpais = 1 and idtemporada = 1 and idcategoria = 1;
and what I want is to add the results, something like this:
sum(casa + visitante) as goles
I suspect this is the query you want:
select sum(case when idcasa = 254 then gcasa else 0 end) as casa,
sum(case when idvisitante = 254 then gvisitante else 0 end) as visitante,
sum(case when idcasa = 254 then gcasa else gvisitante end) as total
from partido
where (idcasa = 254 or idvisitante = 254) and
idpais = 1 and
idtemporada = 1 and
idcategoria = 1;
First, note the change to the where clause -- the parentheses. I am guessing this is the logic your really intend.
Second, it is simple enough to just add the values in an expression. You can use a subquery to define the values first and just add them, but the expression is simple enough. And, subqueries usually incur performance overheads in MySQL.
Third, I replaced the if with case. The latter is the ANSI standard for conditional expressions.
WITH temp AS (
select
sum(if(idcasa = 254, gcasa, 0)) as casa,
sum(if(idvisitante = 254, gvisitante, 0)) as visitante
from partido
where
idcasa = 254 or idvisitante = 254
and idpais = 1
and idtemporada = 1
and idcategoria = 1
)
SELECT sum(casa + visitante) as goles FROM temp;

SQL ORDER BY query

I want to have my table,rcarddet, ordered by "SDNO" (not primary key) in ascending order with the exception of "0". So it should turn out to be like:
1
1
2
.
.
10
0
0
My query now is:
SELECT *
FROM `rcarddet`
WHERE `RDATE` = '2011-05-25'
AND `RCNO` = '1'
AND `PLACE` = 'H'
AND `SDNO` != 0
ORDER BY `rcarddet`.`SDNO` ASC;
The easiest way
SELECT * FROM rcarddet
WHERE RDATE = '2011-05-25' and RCNO = '1'and PLACE = 'H'
ORDER BY CASE
WHEN rcarddet.SDNO = 0 THEN [max_number_for_the_type_of_SDNO]
ELSE rcarddet.SDNO
END ASC
SELECT *
FROM `rcarddet`
WHERE `RDATE` = '2011-05-25'
AND `RCNO` = '1'
AND `PLACE` = 'H'
ORDER BY
`SDNO` = 0,
`SDNO`;