I am trying to use two different tables in a CASE statement but am really struggling. Most of my SQL knowledge is self taught so finding it a bit of a struggle!
The result I am trying to achieve is if TC.ClockingStatus WHEN 1 then '24' (1st Table) if not WHEN OP.Status WHEN 'C' THEN 99 WHEN 'I' THEN 50 ELSE 0 END (2nd Table) AS Status.
This is my current statement:
SELECT TOP (100) PERCENT
RTRIM(OP.Standard_Op) AS TaskDescription,
OP.Op_Number AS OpStep,
CAST(CAST(OP.Works_Order_Number AS DECIMAL(12, 2)) AS NVARCHAR(50)) AS OrderCode,
CASE OP.Status
WHEN 'C' THEN 99
WHEN 'I' THEN 50
ELSE 0
END AS Status,
CAST(OP.Op_Number AS varchar(50)) AS OpCode,
CAST(CAST(OP.Works_Order_Number AS decimal(12, 2)) AS nvarchar(50)) + '_' + CAST(OP.Op_Number AS nvarchar(50)) AS JobCode,
TC.ClockingStatus
FROM
dbo.PROGRESS AS OP
INNER JOIN
dbo.vOrcData_ActiveOperations AS AW ON AW.Works_Order = OP.Works_Order_Number
AND AW.Op_Number = OP.Op_Number
INNER JOIN
dbo.WOHEAD AS WH ON WH.Works_Order = OP.Works_Order_Number
INNER JOIN
dbo.RESOURCE AS RR ON RR.Resource_Code = OP.Original_Resource_Code
LEFT OUTER JOIN
dbo.Techman_WOCLOCK AS TC ON OP.Works_Order_Number = TC.OrderCode
AND OP.Op_Number = TC.OpStep
LEFT OUTER JOIN
dbo.MEMO_FIELDS_SQL ON dbo.MEMO_FIELDS_SQL.Memo_Unique = OP.Man_Memo_Unique
LEFT OUTER JOIN
(SELECT
Allocated_WO_Num, Sub_Con_Op_No,
MAX(Date_Promised) AS Date_Promised
FROM
dbo.PODETAIL AS PODETAIL_1
GROUP BY
Allocated_WO_Num, Sub_Con_Op_No) AS PODETAIL ON PODETAIL.Allocated_WO_Num = OP.Works_Order_Number
AND PODETAIL.Sub_Con_Op_No = OP.Op_Number
LEFT OUTER JOIN
(SELECT
Works_Order, Operation,
SUM(Operation_Time) AS TimeComplete
FROM
dbo.WOCLOCK
GROUP BY
Works_Order, Operation) AS CLOCKEDTIME ON WH.Works_Order = CLOCKEDTIME.Works_Order AND OP.Op_Number = CLOCKEDTIME.Operation
It's possible to use different columns/expressions in a case statement,
but you can't name the column before the first WHEN, like you do.
Try this:
CASE
WHEN TC.ClockingStatus = 1 THEN 24
WHEN OP.Status = 'C' THEN 99
WHEN OP.Status = 'I' THEN 50
ELSE 0 END
The expressions inside a WHEN test can be as complicated as you like. You can even nest CASE statements:
CASE
WHEN TC.ClockingStatus = 1 THEN 24
ELSE CASE OP.Status
WHEN 'C' THEN 99
WHEN 'I' THEN 50
ELSE 0
END
END
I think your problem is that you are trying to use the CASE form:
CASE <Field> WHEN <Value> THEN <Result>
What you need to use is the form:
CASE WHEN <Any condition no matter how complicated> THEN <Result>
Example:
CASE OP.Status WHEN 'C' THEN 99 ELSE 0 END
Can also be used as:
CASE WHEN OP.Status='C' THEN 99 ELSE 0 END
Related
I been struggling to optimize this query,
SELECT
dbo.OE61BLIN.Order_Key
,dbo.OE61BLIN.Doc_Type
,dbo.OE61BHED.Doc__
,dbo.OE61BHED.Inv_Date
,dbo.OE61BHED.Cust__
,dbo.OE61BLIN.Line_Type
,dbo.OE61BLIN.Item__
,dbo.OE61BLIN.Description
,(CASE
WHEN dbo.OE61BLIN.Doc_Type = 'I' THEN dbo.OE61BLIN.Qty_Shipped * dbo.OE61BLIN.Unit_Factor
WHEN dbo.OE61BLIN.Doc_Type = 'C' AND
dbo.OE61BLIN.return_to_inventory_ = 1 THEN -dbo.OE61BLIN.Qty_Shipped * dbo.OE61BLIN.Unit_Factor
ELSE 0
END) AS QTY
,(CASE
WHEN dbo.OE61BLIN.Doc_Type = 'I' THEN dbo.OE61BLIN.Ext_Price
WHEN dbo.OE61BLIN.Doc_Type = 'C' THEN -dbo.OE61BLIN.Ext_Price
ELSE 0
END) * (CASE
WHEN ISNULL(dbo.OE61BHED.Inv_Disc__, 0) <> 0 THEN 1 - (dbo.OE61BHED.Inv_Disc__ / 100)
ELSE 1
END)
AS amount
,dbo.OE61BHED.Inv_Disc__
,dbo.OE61BLIN.ITEM_GROUP
,dbo.OE61BLIN.Category
,ISNULL(dbo.AR61ACST.intercompany, 0) AS intercompany
FROM dbo.OE61BHED
LEFT OUTER JOIN dbo.AR61ACST
ON dbo.OE61BHED.Cust__ = dbo.AR61ACST.Cust__
RIGHT OUTER JOIN dbo.OE61BLIN
ON dbo.OE61BHED.Order_Key = dbo.OE61BLIN.Order_Key
WHERE (dbo.OE61BLIN.Line_Type = 'R')
AND isnull(intercompany,0) != 1
AND (dbo.OE61BLIN.Doc_Type = 'C'
OR dbo.OE61BLIN.Doc_Type = 'I')
Complete estimated execution plan is here
https://www.brentozar.com/pastetheplan/?id=S1htt0rxN
Actual Exectuion Plan
https://www.brentozar.com/pastetheplan/?id=BymztxLgE
I use SQL Sentry Plan Explorer to optimaze it ,
and it suggested that I should add the following two indexes, which I have
But it doesnt improve much, It only removed RID Look Up from plan.
CREATE NONCLUSTERED INDEX [XI_LineTypeDocType_OE61BLIN_12172018]
ON [dbo].[OE61BLIN] ([Line_Type],[Doc_Type])
INCLUDE ([Order_Key],[Item__],[Description],[Category],[Return_to_Inventory_],[Unit_Factor],[Qty_Shipped],[Ext_Price],[ITEM_GROUP])
CREATE INDEX [XI_CustIntercompany_AR67ACST_12172018] ON [GarbageMark].[dbo].[AR61ACST]
([Cust__] ASC)
INCLUDE ([Intercompany])
I am completely stuck on how to aproach this problem.
I see that Lazy Spool is the most expensive operation but I dont know how to remove
or substitute.
Regrettably you don't prefix intercompany in the where clause with its table name so to some extent I'm guessing that the changes you see below. I am going to suggest that you re-arrange your query to avoid the use of right outer join and then, perhaps more importantly, place the intercompany <> 1 condition directly into the left join which
removes the use of ISNULL() from your where clause.
SELECT
dbo.OE61BLIN.Order_Key
, dbo.OE61BLIN.Doc_Type
, dbo.OE61BHED.Doc__
, dbo.OE61BHED.Inv_Date
, dbo.OE61BHED.Cust__
, dbo.OE61BLIN.Line_Type
, dbo.OE61BLIN.Item__
, dbo.OE61BLIN.Description
, (CASE
WHEN dbo.OE61BLIN.Doc_Type = 'I' THEN dbo.OE61BLIN.Qty_Shipped * dbo.OE61BLIN.Unit_Factor
WHEN dbo.OE61BLIN.Doc_Type = 'C' AND
dbo.OE61BLIN.return_to_inventory_ = 1 THEN -dbo.OE61BLIN.Qty_Shipped * dbo.OE61BLIN.Unit_Factor
ELSE 0
END) AS QTY
, (CASE
WHEN dbo.OE61BLIN.Doc_Type = 'I' THEN dbo.OE61BLIN.Ext_Price
WHEN dbo.OE61BLIN.Doc_Type = 'C' THEN -dbo.OE61BLIN.Ext_Price
ELSE 0
END) * (CASE
WHEN ISNULL( dbo.OE61BHED.Inv_Disc__, 0 ) <> 0 THEN 1 - (dbo.OE61BHED.Inv_Disc__ / 100)
ELSE 1
END)
AS amount
, dbo.OE61BHED.Inv_Disc__
, dbo.OE61BLIN.ITEM_GROUP
, dbo.OE61BLIN.Category
, ISNULL( dbo.AR61ACST.intercompany, 0 ) AS intercompany
FROM dbo.OE61BLIN
INNER JOIN dbo.OE61BHED ON dbo.OE61BLIN.Order_Key = dbo.OE61BHED.Order_Key
LEFT OUTER JOIN dbo.AR61ACST ON dbo.OE61BHED.Cust__ = dbo.AR61ACST.Cust__
AND dbo.AR61ACST.intercompany != 1
WHERE dbo.OE61BLIN.Line_Type = 'R'
AND dbo.OE61BLIN.Doc_Type IN ('C','I')
;
I believe the join between OE61BLIN and OE61BHED can be an inner join, if not try using a left join.
I have a sql statement with many inner join tables, as you can see below I have many conditional SUM statements , these sums are giving me wrong (very large) numbers as the inner join is repeating the same values in my source select pool. I was wondering id there is a way to limit these sum conditions lets say to EMPLIDs. The code is :
SELECT
A.EMPL_CTG,
B.DESCR AS PrName,
SUM(A.CURRENT_COMPRATE) AS SALARY_COST_BUDGET,
SUM(A.BUDGET_AMT) AS BUDGET_AMT,
SUM(A.BUDGET_AMT)*100/SUM(A.CURRENT_COMPRATE) AS MERIT_GOAL,
SUM(C.FACTOR_XSALARY) AS X_Programp,
SUM(A.FACTOR_XSALARY) AS X_Program,
COUNT(A.EMPLID) AS EMPL_CNT,
COUNT(D.EMPLID),
SUM(CASE WHEN A.PROMOTION_SECTION = 'Y' THEN 1 ELSE 0 END) AS PRMCNT,
SUM(CASE WHEN A.EXCEPT_IND = 'Y' THEN 1 ELSE 0 END) AS EXPCNT,
(SUM(CASE WHEN A.PROMOTION_SECTION = 'Y' THEN 1 ELSE 0 END)+SUM(CASE WHEN A.EXCEPT_IND = 'Y' THEN 1 ELSE 0 END))*100/(COUNT(A.EMPLID)) AS PEpercent
FROM
EMP_DTL A INNER JOIN EMPL_CTG_L1 B ON A.EMPL_CTG = B.EMPL_CTG
INNER JOIN
ECM_PRYR_VW C ON A.EMPLID=C.EMPLID
INNER JOIN ECM_INELIG D on D.EMPL_CTG=A.EMPL_CTG and D.YEAR=YEAR(getdate())
WHERE
A.YEAR=YEAR(getdate())
AND B.EFF_STATUS='A'
GROUP BY
A.EMPL_CTG,
B.DESCR
ORDER BY B.DESCR
I already tried moving D.YEAR=YEAR(getdate()) to the where clause. Any help would be greatly appereciated
The probable reason of your very large numbers is probably due to the result of Cartesian product of joining A -> B, A -> C and A -> D where tables C and D appear to have multiple records. So, just example... if A has 10 records, and C has 10 for each of the A records, you now have 10 * 10 records... Finally, join that to D table with 10 records, you now have 10 * 10 * 10 for each "A", thus your bloated answers.
Now, how to resolve. I have taken your "C" and "D" tables and "Pre-Aggregated" those counts based on the join column basis. This way, they will each have only 1 record with the total already computed at that level, joined back to A table and you lose your Cartesian issue.
Now, for table B, it appears that is a lookup table only and would only be a single record result anyhow.
SELECT
A.EMPL_CTG,
B.DESCR AS PrName,
SUM(A.CURRENT_COMPRATE) AS SALARY_COST_BUDGET,
SUM(A.BUDGET_AMT) AS BUDGET_AMT,
SUM(A.BUDGET_AMT)*100/SUM(A.CURRENT_COMPRATE) AS MERIT_GOAL,
PreAggC.X_Programp,
SUM(A.FACTOR_XSALARY) AS X_Program,
COUNT(A.EMPLID) AS EMPL_CNT,
PreAggD.DCount,
SUM(CASE WHEN A.PROMOTION_SECTION = 'Y' THEN 1 ELSE 0 END) AS PRMCNT,
SUM(CASE WHEN A.EXCEPT_IND = 'Y' THEN 1 ELSE 0 END) AS EXPCNT,
( SUM( CASE WHEN A.PROMOTION_SECTION = 'Y' THEN 1 ELSE 0 END
+ CASE WHEN A.EXCEPT_IND = 'Y' THEN 1 ELSE 0 END ) *
100 / COUNT(A.EMPLID) AS PEpercent
FROM
EMP_DTL A
INNER JOIN EMPL_CTG_L1 B
ON A.EMPL_CTG = B.EMPL_CTG
AND B.EFF_STATUS='A'
INNER JOIN ( select
C.EMPLID,
SUM(C.FACTOR_XSALARY) AS X_Programp
from
ECM_PRYR_VW C
group by
C.EMPLID ) PreAggC
ON A.EMPLID = PreAggC.EMPLID
INNER JOIN ( select
D.EMPLID,
COUNT(*) AS DCount
from
ECM_INELIG D
where
D.Year = YEAR( getdate())
group by
D.EMPLID ) PreAggD
ON A.EMPLID = PreAggD.EMPLID
WHERE
A.YEAR=YEAR(getdate())
GROUP BY
A.EMPL_CTG,
B.DESCR
ORDER BY
B.DESCR
i'm trying to update a table that is alimented by 2 flows, the 1st one i have to make FillRateCode (the column i want to update) equal to FillRateCode from BWH_OTC_Order but for the 2nd flow i put it equal to '-1'
this is my script:
use BITS
;with tmp as (
select SalesOrderItemNum, SalesOrderNum, FillRateCode
From
BWH_OTC_Order
INNER JOIN REF_Company Comp
ON (Comp.CompanyCode= BWH_OTC_Order.CompanyCode AND Comp.DivisionCode='TEE')
where RevisedPGIDate is not null
)
UPDATE bits_tee.dbo.DMT_TEE_OTC_OrderFulFill
SET FillRateCode = case when exists ( select 1 from tmp) then tmp.FillRateCode else '-1' end
FROM bits_tee.dbo.DMT_TEE_OTC_OrderFulFill DMT
left outer join tmp
on tmp.SalesOrderItemNum = DMT.SalesOrderItemNum
and tmp.SalesOrderNum = DMT.SalesOrderNum
and this is the result i get
NB BWH_FillRateCode DMT_FillRateCode
124457 NULL NULL
73991 0 0
457507 1 1
28632 -1 -1
4849 2 2
34262 3 3
for nulls the correct resault is to get '-1' in DMT_FillRateCode
any issues?
Thx by advence
You can use ISNULL or COALESCE to replace NULL with something else. Your exists( select 1 from tmp) is pointless since it only checks if there are any rows (so not only related rows).
WITH tmp
AS (SELECT SalesOrderItemNum,
SalesOrderNum,
FillRateCode
FROM BWH_OTC_Order
INNER JOIN REF_Company Comp
ON ( Comp.CompanyCode = BWH_OTC_Order.CompanyCode
AND Comp.DivisionCode = 'TEE' )
WHERE RevisedPGIDate IS NOT NULL)
UPDATE DMT
SET DMT.FillRateCode = ISNULL(tmp.FillRateCode, '-1')
FROM bits_tee.dbo.DMT_TEE_OTC_OrderFulFill DMT
LEFT OUTER JOIN tmp
ON tmp.SalesOrderItemNum = DMT.SalesOrderItemNum
AND tmp.SalesOrderNum = DMT.SalesOrderNum
Maybe I'm misinterpreting your question, but if you just want to replace null values with -1 you can use the isnull function
isnull(tmp.FillRateCode,-1) -- I'm guessing the -1 is an int, and not a char '-1'
instead of
case when exists ( select 1 from tmp) then tmp.FillRateCode else '-1' end
Scenario: I am building a report in Excel to calculate commissions. This is based on Invoices from the previous month.
I created the following tsql query and created a connection using MSQuery. I tested the query and it works perfect until I change my Where statement to use the parameter "?" so I can , then I get the following error:
Incorrect Syntax near the keyword `'SELECT'`
Here is the query:
SELECT v_rpt_Invoices.Invoice_Number, v_rpt_Invoices.Territory, v_rpt_Company.Account_Nbr, v_rpt_Invoices.Company_Name, v_rpt_Invoices.Date_Invoice,
v_rpt_Invoices.Location, v_rpt_Invoices.TicketNbr, v_rpt_Invoices.Project_ID, v_rpt_Invoices.Invoice_Type, v_rpt_Invoices.Status_Description,
CASE WHEN TicketNbr <> 0 THEN 'Service Ticket' WHEN Project_ID IS NOT NULL THEN 'Project' ELSE 'Other' END AS Invoice_For,
CASE WHEN ticketNbr <> 0 THEN
(SELECT v_rpt_Service.Board_Name
FROM v_rpt_Service
WHERE v_rpt_Invoices.TicketNbr = v_rpt_Service.TicketNbr) WHEN Project_ID IS NOT NULL THEN Project_ID ELSE 'Other' END AS Service_Board_Project,
CASE WHEN TicketNbr <> 0 THEN
(SELECT Bill_Method
FROM SR_Service
WHERE v_rpt_Invoices.TicketNbr = SR_Service.SR_Service_RecID) WHEN project_id IS NOT NULL THEN
(SELECT PM_Billing_Method_ID
FROM PM_Project
WHERE v_rpt_Invoices.PM_Project_RecID = PM_Project.PM_Project_RecID) ELSE 'NONE' END AS BillingMethod, v_rpt_Invoices.Invoice_Amount,
CASE WHEN (TicketNbr <> 0 AND
(SELECT Bill_Method
FROM SR_Service
WHERE v_rpt_Invoices.TicketNbr = SR_Service.SR_Service_RecID) = 'A') THEN Invoice_Amount * 0.7 WHEN (TicketNbr <> 0 AND
(SELECT Bill_Method
FROM SR_Service
WHERE v_rpt_Invoices.TicketNbr = SR_Service.SR_Service_RecID) = 'F') THEN 0.01 WHEN (project_id IS NOT NULL AND
(SELECT PM_Billing_Method_ID
FROM PM_Project
WHERE v_rpt_Invoices.PM_Project_RecID = PM_Project.PM_Project_RecID) = 'A') THEN Invoice_Amount * 0.7 WHEN (project_id IS NOT NULL AND
(SELECT PM_Billing_Method_ID
FROM PM_Project
WHERE v_rpt_Invoices.PM_Project_RecID = PM_Project.PM_Project_RecID) = 'F') THEN 0.01 ELSE 0.00 END AS Cost
FROM v_rpt_Invoices INNER JOIN
v_rpt_Company ON v_rpt_Invoices.Company_RecID = v_rpt_Company.Company_RecID
**WHERE (v_rpt_Invoices.Date_Invoice >= ?)**
order by Territory, Invoice_For
Remove this line
**WHERE (v_rpt_Invoices.Date_Invoice >= ?)**
That is not valid SQL -- looks like you want to comment use double dash.
Unless you are just putting the ** to show what you changed. In that case you need to have a value where the ? is the SQL won't work.
As an asside, this query could be made much clearer and faster. Consider consolidating sub-queries into a join. For example, the following sub-query
SELECT Bill_Method
FROM SR_Service
WHERE v_rpt_Invoices.TicketNbr = SR_Service.SR_Service_RecID
MUST be called for every row -- if you make this a join you go from O(nm) to O(n+m) Where n is the size of v_rpt_Invoices and m is the size of SR_Service.
This is just one of the potential sub-queries you can optimize.
Here is an example of rolling in the sub-queries to your example
(I can't test so it might have bugs / typos)
SELECT
v_rpt_Invoices.Invoice_Number,
v_rpt_Invoices.Territory,
v_rpt_Company.Account_Nbr,
v_rpt_Invoices.Company_Name,
v_rpt_Invoices.Date_Invoice,
v_rpt_Invoices.Location,
v_rpt_Invoices.TicketNbr,
v_rpt_Invoices.Project_ID,
v_rpt_Invoices.Invoice_Type,
v_rpt_Invoices.Status_Description,
CASE WHEN TicketNbr <> 0 THEN 'Service Ticket'
WHEN Project_ID IS NOT NULL THEN 'Project'
ELSE 'Other'
END AS Invoice_For,
CASE WHEN ticketNbr <> 0 THEN v_rpt_Service.Board_Name
WHEN Project_ID IS NOT NULL THEN Project_ID
ELSE 'Other'
END AS Service_Board_Project,
CASE WHEN TicketNbr <> 0 THEN SR_Service.Bill_Method
WHEN project_id IS NOT NULL THEN PM_Project.PM_Billing_Method_ID
ELSE 'NONE'
END AS BillingMethod, v_rpt_Invoices.Invoice_Amount,
CASE WHEN (TicketNbr <> 0 AND SR_Service.Bill_Method ='A') THEN Invoice_Amount * 0.7
WHEN (TicketNbr <> 0 AND SR_Service.Bill_Method ='F') THEN 0.01
WHEN (project_id IS NOT NULL AND PM_Project.PM_Billing_Method_ID = 'A') THEN Invoice_Amount * 0.7
WHEN (project_id IS NOT NULL AND PM_Project.PM_Billing_Method_ID = 'F') THEN 0.01
ELSE 0.00
END AS Cost
FROM v_rpt_Invoices
INNER JOIN v_rpt_Company ON v_rpt_Invoices.Company_RecID = v_rpt_Company.Company_RecID
LEFT JOIN SR_Service ON v_rpt_Invoices.TicketNbr = SR_Service.SR_Service_RecID
LEFT JOIN PM_Project ON v_rpt_Invoices.PM_Project_RecID = PM_Project.PM_Project_RecID
LEFT JOIN v_rpt_Service ON v_rpt_Invoices.TicketNbr = v_rpt_Service.TicketNbr
WHERE (v_rpt_Invoices.Date_Invoice >= '1/1/2013')
order by Territory, Invoice_For
I have the following query:
SELECT c.danhoEstetico, c.danhoDirecto
FROM conceptos c
INNER JOIN materialesconceptos mc ON mc.idConcepto = c.idConcepto
INNER JOIN materiales m ON m.idMaterial = mc.idMaterial
WHERE m.idMaterial IN (4,11,11)
Which yields the following result (for example):
danhoEstetico | danhoDirecto
1 | 0
1 | 0
0 | 0
0 | 0
I need to make a query that gives me if any of the items in each column has a 1, like an OR among all the fields in the same column, with an output like:
danhoEstetico | danhoDirecto
1 | 0
I have tried:
SELECT
SUM(CASE c.danhoEstetico WHEN c.danhoEstetico=1 THEN 1 ELSE 0 END) AS de,
SUM(CASE c.danhoDirecto WHEN c.danhoDirecto=1 THEN 1 ELSE 0 END) AS dd
FROM conceptos c INNER JOIN materialesconceptos mc ON mc.idConcepto = c.idConcepto
INNER JOIN materiales m ON m.idMaterial = mc.idMaterial
WHERE m.idMaterial IN (4,11,11)
Which, for some reason, yields:
danhoEstetico | danhoDirecto
4 | 4
Any hint on this?
To get the largest value in each column, use MAX instead of SUM.
Edit: I misread the question. This solution checks that every row in a column is 1, rather than any row. I recommend CL's answer, but I will leave this answer here because it explains a problem with the CASE statement in the question.
You should be using CASE without a base expression:
SELECT
SUM(CASE WHEN c.danhoEstetico=1 THEN 1 ELSE 0 END) AS de,
SUM(CASE WHEN c.danhoDirecto=1 THEN 1 ELSE 0 END) AS dd
FROM conceptos c INNER JOIN materialesconceptos mc ON
mc.idConcepto = c.idConcepto
INNER JOIN materiales m ON m.idMaterial = mc.idMaterial
WHERE m.idMaterial IN (4,11,11)
From the documentation:
In a CASE with a base expression, the base expression is evaluated
just once and the result is compared against the evaluation of each
WHEN expression from left to right. The result of the CASE expression
is the evaluation of the THEN expression that corresponds to the first
WHEN expression for which the comparison is true...
In your statement as written, the case statement always evaluated to 1 when the column was 1 and 0 when the column was 0. Thus, they always matched, and the sum was always the number of rows.
Update: now how do you actually turn this into the result you want? Here is one way:
SELECT
SUM(CASE WHEN c.danhoEstetico=1 THEN 1 ELSE 0 END) / SUM(1) AS de,
SUM(CASE WHEN c.danhoDirecto=1 THEN 1 ELSE 0 END) / SUM(1) AS dd
FROM conceptos c INNER JOIN materialesconceptos mc ON
mc.idConcepto = c.idConcepto
INNER JOIN materiales m ON m.idMaterial = mc.idMaterial
WHERE m.idMaterial IN (4,11,11)
This takes advantage of integer arithmetic. The division will result in a value < 1 if not all rows in a column are one, and a value less than one will show as zero.
select distinct
c.danhoEstetico, c.danhoDirecto
FROM conceptos c
INNER JOIN materialesconceptos mc ON mc.idConcepto = c.idConcepto
INNER JOIN materiales m ON m.idMaterial = mc.idMaterial
where 1 in (c.danhoEstetico , c.danhoDirecto)