Using a CASE WHEN statement and an IN (SELECT...FROM) subquery - sql

I'm trying to create a temp table and build out different CASE WHEN logic for two different medications. In short I have two columns of interest for these CASE WHEN statements; procedure_code and ndc_code. There are only 3 procedure codes that I need, but there are about 20 different ndc codes. I created a temp.ndcdrug1 temp table with these ndc codes for medication1 and temp.ndcdrug2 for the ndc codes for medication2 instead of listing out each ndc code individually. My query looks like this:
CREATE TABLE temp.flags AS
SELECT DISTINCT a.userid,
CASE WHEN (procedure_code = 'J7170' OR ndc_code in (select ndc_code from temp.ndcdrug1)) THEN 'Y' ELSE 'N' END AS Drug1,
CASE WHEN (procedure_code = 'J7205' OR procedure_code = 'C9136' OR ndc_code in (select ndc_code from temp.ndcdrug2)) THEN 'Y' ELSE 'N' END AS Drug2,
CASE WHEN (procedure_code = 'J7170' AND procedure_code = 'J7205') THEN 'Y' ELSE 'N' END AS Both
FROM table1 a
LEFT JOIN table2 b
ON a.userid = b.userid
WHERE...
AND...
When I run this, it returns: org.apache.spark.sql.AnalysisException: IN/EXISTS predicate sub-queries can only be used in a Filter.
I could list these ndc_code values out individually, but there are a lot of them so wanted a more efficient way of going about this. Is there a way to use a sub select query like this when writing out CASE WHEN's?

Query.
CREATE TABLE temp.flags AS
SELECT DISTINCT a.userid,
CASE WHEN (
procedure_code = 'J7170' OR
(select min('1') from temp.ndcdrug1 m where m.ndc_code = a.ndc_code) = '1'
) THEN 'Y' ELSE 'N' END AS Drug1,
CASE WHEN (
procedure_code = 'J7205' OR
procedure_code = 'C9136' OR
(select min('1') from temp.ndcdrug2 m where m.ndc_code = a.ndc_code) = '1'
) THEN 'Y' ELSE 'N' END AS Drug2,
CASE WHEN (procedure_code = 'J7170' AND procedure_code = 'J7205')
THEN 'Y' ELSE 'N' END AS Both
FROM table1 a
LEFT JOIN table2 b
ON a.userid = b.userid
WHERE...
AND...

Related

Cannot use an aggregate or a subquery

I'm trying to group this case expression but unfortunately I'm getting an error.
select da.order_id, osl.itemid, sum(case when osl.sku = '00005' then 0 when osl.sku = '00006' then 0 else osl.price * sil.quantity end) merchcost, sum(sil.merchUnitCost * sil.quantity) cogs, sum(sil.quantity) quantity,
CASE
WHEN EXISTS (SELECT * FROM fcat.dbo.subscriptionskus a where a.itemId = osl.itemid) then 1
WHEN EXISTS (SELECT * FROM foam.dbo.subscriptionprogram b where b.orderStateLineId = osl.orderStateLine_id ) then 1
else 0
END as isAdmin,
CASE
WHEN EXISTS (SELECT * FROM fcat.dbo.subscriptionskus a where a.itemId = osl.itemid) then CAST('subscriptionskus' as varchar(MAX))
WHEN EXISTS (SELECT * FROM foam.dbo.subscriptionprogram b where b.orderStateLineId = osl.orderStateLine_id ) then CAST('subscriptionprogram' as varchar(MAX))
else 'NotListed'
END as SubTable
from #dispatchAmounts da
inner join orderstates os on os.order_id = da.order_id
inner join orderstatelines osl on osl.orderState_id = os.orderState_id
inner join shippingIntentLines sil on sil.orderStateLine_id = osl.orderStateLine_id and da.shippingIntent_nbr = sil.shippingIntent_nbr
where da.code = 'merch' and sil.quantity > 0
group by da.order_id, osl.itemid, CASE
WHEN EXISTS (SELECT * FROM fcat.dbo.subscriptionskus a where a.itemId = osl.itemid) then 1
WHEN EXISTS (SELECT * FROM foam.dbo.subscriptionprogram b where b.orderStateLineId = osl.orderStateLine_id ) then 1
else 0
END,CASE
WHEN EXISTS (SELECT * FROM fcat.dbo.subscriptionskus a where a.itemId = osl.itemid) then CAST('subscriptionskus' as varchar(MAX))
WHEN EXISTS (SELECT * FROM foam.dbo.subscriptionprogram b where b.orderStateLineId = osl.orderStateLine_id ) then CAST('subscriptionprogram' as varchar(MAX))
else 'NotListed'
END
ERROR:
Cannot use an aggregate or a subquery in an expression used for the group by list of a GROUP BY clause.
Is there anyway I can make this work?
I have a couple of suggestions. You are using select * in your case statements , but the columns referenced by '*' are not in your group by clause. To add them would be a bad way to fix the problem. Instead use ' select 1 ' and see what happens.
Second recommendation is to just not use the when exists rather use left join using sub queries and use those in your case statements.
So what I did is.
1. Removed the Case Statement on the Group By.
2. Modified the SubQueries on the Case Statement. Followed #Shiv Sidhu recommendation.
Thanks for everyone.

Combine 3 big tables with 2 joins

I have three tables using complex. I run them separately without problems. Here are the queries:
TABLE A:
select
maxxx.id_demande_diffusion AS ID_DIFFUSION,
maxxx.id_notification as ID_NOTIFICATION,
maxxx.cd_organisation_client as ID_ENTITE,
maxxx.cod_entrep as ID_ENTITE_GARANTE,
maxxx.cd_canal as CD_CANAL,
maxxx.id_demande_diffusion_originale as ID_DIFFUSION_PARENT,
maxxx.ref_maquette as REF_MAQUETTE,
maxxx.qualification_canal as QUALIFICATION_CANAL,
maxxx.ger_id_pli as ID_PLI_GER,
case when maxxx.typ_mvt="S" then 1 else 0 end AS TOP_SUPP,
case when maxxx.typ_mvt = "S" then to_date(substr(maxxx.dt_capt, 1, 11)) else null end AS DT_SUPP,
minnn.typ_mvt as MIN_MVT,
maxxx.typ_mvt as MAX_MVT,
case when minnn.typ_mvt = 'C' then 'C' else 'M' end as TYP_MVT
from
(select s.id_demande_diffusion, s.dt_capt, s.typ_mvt from ${use_database}.pz_send_demande_diffusion as s
join
(select id_demande_diffusion, min(dt_capt) as dtmin from ${use_database}.pz_send_demande_diffusion group by id_demande_diffusion) as minn
on minn.id_demande_diffusion=s.id_demande_diffusion and s.dt_capt=minn.dtmin ) as minnn
join
(select s.id_demande_diffusion, s.typ_mvt, s.id_notification, s.dt_capt, s.cd_organisation_client, s.cod_entrep, s.cd_canal, s.id_demande_diffusion_originale,
s.ref_maquette, s.qualification_canal, s.ger_id_pli from ${use_database}.pz_send_demande_diffusion as s
join
(select id_demande_diffusion, max(dt_capt) as dtmax from ${use_database}.pz_send_demande_diffusion group by id_demande_diffusion) as maxx
on s.id_demande_diffusion=maxx.id_demande_diffusion and s.dt_capt=maxx.dtmax)as maxxx
on minnn.id_demande_diffusion=maxxx.id_demande_diffusion;
TABLE B:
select
maxxx.id_notification as ID_NOTIFICATION,
maxxx.cd_type_destinataire as CD_TYPE_DESTINATAIRE,
case when maxxx.cd_type_destinataire = "IDGRC" then maxxx.destinataire else null end AS ID_PERSONNE,
case when maxxx.cd_type_destinataire = "MAIL" then maxxx.destinataire else null end AS EMAIL_DESTINATAIRE,
case when maxxx.cd_type_destinataire = "SMS" then maxxx.destinataire else null end AS NUM_TEL_DESTINATAIRE,
maxxx.cd_type_evenement,
maxxx.cd_type_notification,
maxxx.cd_type_destinataire_source AS CD_TYPE_DEST_SOURCE,
case when maxxx.cd_type_destinataire_source = "IDGRC" then maxxx.destinataire_source when maxxx.cd_type_destinataire_source = "IDGRC|IDGRC" then substr(maxxx.destinataire_source, 1, locate("|", maxxx.destinataire_source)-1) else null end AS ID_PERS_DEST_SOURCE,
case when maxxx.cd_type_destinataire_source = "SIGMA" or maxxx.cd_type_destinataire_source = "CUBA" then maxxx.destinataire_source else null end AS REF_EXT_DEST_SOURCE,
case when maxxx.cd_type_destinataire_source = "MAIL" then maxxx.destinataire_source else null end AS EMAIL_DEST_SOURCE,
case when maxxx.cd_type_destinataire_source = "SMS" then maxxx.destinataire_source else null end AS NUM_TEL_DEST_SOURCE,
case when maxxx.cd_type_destinataire_source = "IDGRC|IDGRC" then substr(maxxx.destinataire_source, locate("|", maxxx.destinataire_source)+1, length(maxxx.destinataire_source)) end AS ID_PERSONNE_DEST_SOURCE_2
from
(select n.id_notification, n.destinataire, n.cd_type_evenement, n.cd_type_notification, n.destinataire_source, n.cd_type_destinataire, n.cd_type_destinataire_source from ${use_database}.pz_send_notification as n
join
(select id_notification, max(dt_capt) as dtmax from ${use_database}.pz_send_notification group by id_notification) as maxx
on n.id_notification=maxx.id_notification and n.dt_capt=maxx.dtmax) as maxxx;
TABLE C:
select
maxxx.id_communication AS ID_COMMUNICATION,
maxxx.cd_sa as CD_SYS_DIFFUSEUR,
maxxx.type_conteneur as CD_TYPE_CONTENEUR
from
(select n.id_communication, n.cd_sa, n.type_conteneur from ${use_database}.pz_send_comm_retour as n
join
(select id_communication, max(dt_capt) as dtmax from ${use_database}.pz_send_comm_retour group by id_communication) as maxx
on n.id_communication=maxx.id_communication and n.dt_capt=maxx.dtmax) as maxxx;
Is there anyway to combine the three of the using one join and one left join ?
I want o have something like
SELECT * FROM (TABLE A join TABLE B ON A.ID_NOTIFICATION=B.ID_NOTIFICATION) AS TMP LEFT JOIN TABLE C ON TMP.ID_DIFFUSION=C.ID_COMMUNICATION;
I have been trying but it always fails because of missing or misplaced parenthesis.
Thank you!
I have no idea if your queries are correct, but common table expressions (CTE) can frequently be used to keep result set joins clean.
WITH TABLE_A AS
( SELECT
FROM ...
...
),
TABLE_B AS
( SELECT
FROM ...
...
),
TABLE_C AS
( SELECT
FROM ...
...
)
SELECT *
FROM TABLE_A TA
JOIN TABLE_B TB
ON TA.Key_Field = TB.Key_Field
JOIN TABLE_C TC
ON TB.Key_Field = TC.Key_Field

How to use a non-existing column in sql query

I am working in SQL server 2012. I have to write a sql statement where I first assign a value to [Pay_Type], which is a non-existing column (not sure whether it can be called as variable or not) and based upon its value I want to use it in another case statement as shown below
SELECT sp.First_Name, [Pay_Type] = CASE WHEN NOT EXISTS(SELECT '1' FROM
PERSON_SALARY ps WHERE ps.PARTY_ID = sp.PARTY_ID and ps.END_DATE IS NULL)
THEN 'Hourly' ELSE 'Salary' END,
HOURLY_RATE = CASE WHEN [Pay_Type] = 'Hourly' THEN pj.HOURLY_RATE ELSE
'0.00' END
FROM SEC_PERSON sp
LEFT OUTER JOIN PERSON_JOB pj ON sp.PERSON_ID = pj.PERSON_ID
WHERE sp.END_DATE IS NOT NULL
But I am getting "Invalid column name 'Pay_Type' " error.
Column aliases cannot be re-used in the same SELECT where they are define. The typical answer is to use a subquery or CTE. I also like using a lateral join:
SELECT sp.First_Name, s.Pay_Type,
HOURLY_RATE = (CASE WHEN s.Pay_Type = 'Hourly' THEN pj.HOURLY_RATE ELSE
'0.00' END)
FROM SEC_PERSON sp LEFT OUTER JOIN
PERSON_JOB pj
ON sp.PERSON_ID = pj.PERSON_ID OUTER APPLY
(SELECT (CASE WHEN NOT EXISTS (SELECT 1
FROM PERSON_SALARY ps
WHERE ps.PARTY_ID = sp.PARTY_ID and ps.END_DATE IS NULL
)
THEN 'Hourly' ELSE 'Salary'
END) as PayType
) s
WHERE sp.END_DATE IS NOT NULL

get text from int value in select case of sql query

I need convert int value in a select for string value for human Reading.
I try two forms but any works
select id, case Preparacion when 1 then 'Yes' when 0 then 'No' else preparacion end as Preparación
from pinchos
inner join Laboratorios on Laboratorios.CodKais = Pinchos.codKais
where entradaproduccion = '20140905'
And convert Preparacion to varchar()
select id, case convert(varchar(1),Preparacion) when '1' then 'Yes' when '0' then 'No' else preparacion end as Preparacion
from pinchos
inner join Laboratorios on Laboratorios.CodKais = Pinchos.codKais
where entradaproduccion = '20140905'
how I can show string value?
I only have read permisions in database and dont have Preparación table
Compare as INT and cast when required.
Try this:
(untested code)
select id,
case Preparacion
when 1 then 'Yes'
when 0 then 'No'
else CAST(preparacion as VARCHAR(255))
end as Preparacion
from pinchos
inner join Laboratorios on Laboratorios.CodKais = Pinchos.codKais
where entradaproduccion = '20140905'
You have forgottone an else there
select id, case Preparacion
when 1 then 'Yes'
else
when 0 then 'No' else preparacion end
end as Preparación
from pinchos
inner join Laboratorios on Laboratorios.CodKais = Pinchos.codKais
where entradaproduccion = '20140905'

using CASE WHEN in SQL Statement

I have to display information by comparing data in two ID columns, one column has 'ALL' and numbers as ID's while the other has only numbers in it as ID's. My problem is, I cannot compare character and number columns with a number column. So I am using CASE WHEN.
If the value is 'ALL' then display 'ALL' in the output, else display name for the matching records.
Here is the code:
CASE
WHEN secorg.org_id = 'ALL' THEN 'ALL'
WHEN secorg.org_id = progmap.org_id THEN secorg.org_name
END AS org_name,
the condition is this: 'secorg.org_id = progmap.org_id' which is based on the id and I have to display secorg.org_name if the id's are same.
Here is the entire query:
SELECT distinct program_id,
prog_name,
case
when Eitc_Active_Switch = '1' then 'ON'
when Eitc_Active_Switch = '0'then 'OFF'
End as Prog_Status,
progmap.client_id,
case
when secorg.org_id = 'ALL' then 'ALL'
--when secorg.org_id = progmap.org_id then secorg.org_name
else secorg.org_name
end as org_name,
case
when prog.has_post_calc_screen = 'True' then 'True'
Else 'False'
End as Referal_ID,
case
when progmap.program_ID IN ( 'AMC1931', 'AMCABD', 'AMCMNMI',
'AMC' )
And sec.calwinexists_ind = '1' then 'Yes'
when progmap.program_ID IN ( 'AMC1931', 'AMCABD', 'AMCMNMI',
'AMC' )
And sec.calwinexists_ind = '0'then 'No'
when progmap.program_ID NOT IN (
'AMC1931', 'AMCABD', 'AMCMNMI', 'AMC' ) then
'N/A'
End as calwin_interface,
sec.Client_name
FROM ref_programs prog (nolock)
LEFT OUTER JOIN ref_county_program_map progmap (nolock)
ON progmap.program_id = prog.prog_id
AND progmap.CLIENT_ID = prog.CLIENT_ID
INNER join sec_clients sec (nolock)
on sec.client_id = progmap.Client_id
Inner join sec_organization secorg (nolock)
on secorg.org_id = progmap.org_id
Why not cast the number columns to varchar columns?
If you're using SQL SERVER you can do that like so:
CONVERT(VARCHAR,secorg.org_id) = CONVERT(VARCHAR,progmap.org_id)
You'll have to do an outer join for instances when the column that is both 'ALL' and numbers is 'All' as it won't be able to inner join to the other table.
For the quick fix based on your code above you can just change the second WHEN clause to look like so (again assuming you're using MS SQL SERVER):
WHEN CONVERT(VARCHAR,secorg.org_id) = CONVERT(VARCHAR,progmap.org_id) THEN secorg.org_name
Try this as your query:
SELECT DISTINCT
program_id,
prog_name,
CASE Eitc_Active_Switch
WHEN '1' THEN 'ON'
ELSE 'OFF'
END AS Prog_Status,
progmap.client_id,
ISNULL(secorg.org_name,'ALL') AS org_name,
CASE prog.has_post_calc_screen
WHEN 'True' THEN 'True'
ELSE 'False'
END AS Referal_ID,
CASE WHEN progmap.program_ID IN ('AMC1931','AMCABD','AMCMNMI','AMC') AND sec.calwinexists_ind = '1' THEN
'Yes'
WHEN progmap.program_ID IN ('AMC1931','AMCABD','AMCMNMI','AMC') AND sec.calwinexists_ind = '0' THEN
'No'
WHEN progmap.program_ID NOT IN ('AMC1931','AMCABD','AMCMNMI','AMC') THEN
'N/A'
END AS calwin_interface,
sec.Client_name
FROM
ref_programs prog (nolock)
LEFT OUTER JOIN ref_county_program_map progmap (nolock) ON progmap.program_id = prog.prog_id AND progmap.CLIENT_ID = prog.CLIENT_ID
INNER JOIN sec_clients sec (nolock) ON sec.client_id = progmap.Client_id
LEFT OUTER JOIN sec_organization secorg (nolock) ON CONVERT(VARCHAR,secorg.org_id) = CONVERT(VARCHAR,progmap.org_id)
The case statement is fine its the field alias thats bad it shoud be
END As org_name
A multipart alias like secorg.org_name won't work