SQL Server CASE statement with subquery in then - sql

I have the case statement below but despite it having the values that should trigger the case's, I am still getting nulls. Any obvious errors?
SELECT
*,
(CASE
WHEN topicname = 'TPOSTAL_CODE'
THEN (SELECT LTRIM(RTRIM(ALS_C)) AS LocationCode
FROM ODS.TBUS_LOC
WHERE cci.columna = ods.TBUS_LOC.BUS_LOC_I)
WHEN topicname = 'TBUSINESS_SITE'
THEN (SELECT LTRIM(RTRIM(B.ALS_C)) AS LocationCode
FROM ODS.TBUSINESS_SITE A
INNER JOIN ODS.TBUS_LOC B ON A.BUS_LOC_ID = B.BUS_LOC_I
WHERE cci.columna = A.BUS_LOC_ID)
END) AS Code
FROM
[XREF].[tablea] CCI
CCIEntityName with a distinct

It could be that topicname contains spaces either at the beginning or the end. These may not be readily visible to the eye. You might try
CASE WHEN ltrim(rtrim(topicname)) = 'TPOSTAL_CODE'
and see if that makes a difference.

Related

Case When + IN combination

I'm a bit stuck in my coding here... I have this extense and complex code, but I'm actually failling by the end of it. I'm getting the SQL Error [42804]: ERROR: argument of CASE/WHEN must be type boolean, not type character varying
The thing, is: when "bairro" matches a row from "SUB_COUNTRY_DB", get psd.name, else get z.name. Any tips on how I could accomplish this?
select distinct
aa.mes,
--aa.modalidade,
--to_date(aa.created_date, 'yyyy-mm-dd') data_captacao,
ucl.ja_comprou_lf as comprou_lf,
case when bairro in (select sub_country from sub_country_DB)
then psd.name
else z.name
end loja,
count (distinct aa.customer_uid) qtde_socios,
count (distinct aa.assinatura_uid) qtde_assinaturas
from assinaturas_ativas aa
left join ultima_compra_loja_fisica ucl on (aa.customer_uid = ucl.customer_uid
and aa.mes = ucl.mes)
left join zip_code z on (aa.customer_uid = z.customer_uid
and aa.mes = z.mes)
left join SUB_COUNTRY_DB psd
on (psd.district = aa.bairro)
group by 1,2,3--,4
Try variants like:
moving condition to an inner query
CASE WHEN EXISTS (SELECT DISTINCT sub_country FROM sub_country_DB WHERE sub_country = barrio)
ANY (PostgreSQL only)
CASE WHEN bairro = ANY(ARRAY_AGG(select sub_country from sub_country_DB))

Incorrect syntax near the keyword 'FROM' in SQL Server

Please help me in the code, I get an error
Incorrect syntax near the keyword 'FROM'
SELECT
produkt.Twr_Kod as kod,
(SELECT
ISNULL(SUM(zasoby.TwZ_Ilosc), 0) + ISNULL(SUM(trs_ilosc), 0)
FROM
cdn.TraSElem
WHERE
trs_typ = 3 AND TrS_TrEIdWydania = 0
AND TrS_DataOpe > GETDATE() AND zasoby.TwZ_TwrId = TrS_TwrId
AND zasoby.TwZ_MagId = 1
FROM
CDN.TwrZasoby as zasoby
WHERE
zasoby.Twz_TwrId = product.Twr_twrid) AS zasoby,
CONVERT(NUMERIC(10, 0), produkt.Twr_IloscMin) AS ilosc_minimalna
FROM
CDN.Towary AS product
LEFT JOIN
CDN.Towary AS produkt ON product.Twr_TwrId = produkt.Twr_TwrId
GROUP BY
product.Twr_TwrId, produkt.Twr_Kod, produkt.Twr_IloscMin
ORDER BY
kod
SQLs kinda need to look like this:
SELECT columns FROM tables_or_queries WHERE predicates GROUP BY grouping_keys ORDER BY columns
This pattern can be nested both inside the SELECT region and the FROM region:
SELECT
column1,
(SELECT columnA FROM table WHERE where_predicates) as column2,
column3
FROM
table
INNER JOIN
(SELECT columnA, columnB FROM table WHERE where_predicates) as nested_query
ON join_predicates
WHERE
where_predicates
But you can't have multiple FROM regions etc.. To get more targeted advice youre going to have to tell us what you're hoping your query does.. Right now, we can only say to sort out the basic syntax errors the compilation process is complaining about
You seem to have multiple FROM statements in a single SELECT statement. Every SELECT can have only one FROM clause. Glancing through your query, I think it's going to give you performance nightmares. Use joins instead of using inline queries. Will improve performance.
SELECT
produkt.Twr_Kod as kod,
(SELECT
ISNULL(SUM(zasoby.TwZ_Ilosc), 0) + ISNULL(SUM(trs_ilosc), 0)
**FROM
cdn.TraSElem
WHERE
trs_typ = 3 AND TrS_TrEIdWydania = 0
AND TrS_DataOpe > GETDATE() AND zasoby.TwZ_TwrId = TrS_TwrId
AND zasoby.TwZ_MagId = 1
FROM
CDN.TwrZasoby as zasoby**
WHERE
zasoby.Twz_TwrId = product.Twr_twrid) AS zasoby,
CONVERT(NUMERIC(10, 0), produkt.Twr_IloscMin) AS ilosc_minimalna
FROM
CDN.Towary AS product
LEFT JOIN
CDN.Towary AS produkt ON product.Twr_TwrId = produkt.Twr_TwrId
GROUP BY
product.Twr_TwrId, produkt.Twr_Kod, produkt.Twr_IloscMin
ORDER BY
kod

ORA-00934: group function is not allowed here when adding case when

I have a piece of code which runs fine. However, when i am introducing a "case when" statement in the select clause, I get the "group function is not allowed here" error and I cannot fix it (the issue relates to the last Group by function in my code)
Any idea why (don't be put off by the code, it is 3 joins together, apparently the issue is caused by the last Group By statement) ?
Thank you!
SELECT
Trans_Table.MTAGRE01_NO
, (case when Cash. MTAGRE01_NO = Trans_Table. MTAGRE01_NO
then (SUM(Trans_Table.MTTRANS01_VALUENCU)*-1)
else SUM(Trans_Table.MTTRANS01_VALUENCU) END) AS MTTRANS01_VALUENCU
FROM MTTRANS01 Trans_Table
INNER JOIN RUTRANTYPE01 Trans_Type
ON Trans_Type.RUTRANTYPE01_CODE = Trans_Table.RUTRANTYPE01_CODE
LEFT JOIN(
SELECT
MTAGRE01_NO
,CASE WHEN SRAGRESTAT01_CODE = 'COLL' THEN MTAGRE01_AGRESTATDATE END AS Date_Fr
from MTAGRE01
where CASE WHEN SRAGRESTAT01_CODE = 'COLL' THEN MTAGRE01_AGRESTATDATE END is not null
) F_Date
ON F_Date.MTAGRE01_NO = Trans_Table.MTAGRE01_NO
LEFT JOIN(
SELECT
Trans_Table.MTAGRE01_NO
FROM MTTRANS01 Trans_Table
INNER JOIN RUTRANTYPE01 Trans_Type ON Trans_Type.RUTRANTYPE01_CODE = Trans_Table.RUTRANTYPE01_CODE
GROUP BY
Trans_Table.MTAGRE01_NO, Trans_Type.RUTRANTYPE01_CODE, Trans_Type.RUTRANTYPE01_DESCRIPTION
) Cash
ON Cash.MTAGRE01_NO = Trans_Table.MTAGRE01_NO
where Trans_Type.SRPROCTYPE01_CODE in ('C','D')
and Trans_Table.MTTRANS01_VALUEDATE >= F_Date.Date_Fr
GROUP BY
Trans_Table.MTAGRE01_NO
, (case when Cash. MTAGRE01_NO = Trans_Table. MTAGRE01_NO
then (SUM(Trans_Table.MTTRANS01_VALUENCU)*-1)
else SUM(Trans_Table.MTTRANS01_VALUENCU) END);
I believe it's hung up on the sum inside the case statement. 2 routes to correct that I can see, likely alot more:
This is a little hacky, but it'll work and give results fast. Change your case:
SELECT
Trans_Table.MTAGRE01_NO
, (case when Cash. MTAGRE01_NO = Trans_Table. MTAGRE01_NO
then ((Trans_Table.MTTRANS01_VALUENCU)*-1)
else (Trans_Table.MTTRANS01_VALUENCU) END) AS MTTRANS01_VALUENCU
Remove the case from the group by.
Now call your entire query a sub query
Select MTAGRE01_NO, sum(MTTRANS01_VALUENCU)
(your entire query)a
You other option that takes a bit more work...in your initial from statement:
MTTRANS01 Trans_Table
Change that to a subquery that joins to the trans table and returns
case when Cash. MTAGRE01_NO = Trans_Table. MTAGRE01_NO
then ((Trans_Table.MTTRANS01_VALUENCU)*-1)
else (Trans_Table.MTTRANS01_VALUENCU) END as MTAGRE01_NO
Then join to that subquery and do a simple sum in your main query.
Hopefully that all makes sense, ask questions if you need clarifications

SQL Server Execution Plan Review Request

Having trouble understanding why my query is taking so long, looking for advice to optimise please.
update Laserbeak_Main.dbo.ACCOUNT_MPN set
DateUpgrade = ord.ConnectedDate
FROM [ORDER] ord
WHERE ord.AccountNumber = Laserbeak_Main.dbo.ACCOUNT_MPN.AccountNumber
AND ord.ordertypeID = '2'
AND ord.ConnectedDate IS NOT NULL
AND DateUpgrade <> ord.ConnectedDate
Execution plan as requested on brentozar.com
UPDATE: Following suggestions the new query looks like this & seems to work much more quickly. However if you run the query it sets the rows as expected, then run again it updates the exact same number of rows. Converting to a select confirms that the same rows are being updated each time. The <> clause should stop this but it doesn't. I believed it was something to do with collation but have been unable to confirm if its possible to have different collations at table level in the same database.
;WITH cteOrderInfo AS (
SELECT DISTINCT ord.AccountNumber, ord.ConnectedDate
FROM [ORDER] ord
WHERE ord.ordertypeID = '2'
AND ord.ConnectedDate IS NOT NULL
)
UPDATE Laserbeak_Main.dbo.ACCOUNT_MPN
SET Laserbeak_Main.dbo.ACCOUNT_MPN.DateUpgrade = cteOrderInfo.ConnectedDate
FROM cteOrderInfo
INNER JOIN Laserbeak_Main.dbo.ACCOUNT_MPN acc
ON cteOrderInfo.AccountNumber = acc.AccountNumber
WHERE cteOrderInfo.ConnectedDate <> acc.DateUpgrade
The SELECT to confirm:
;WITH cteOrderInfo AS (
SELECT DISTINCT ord.AccountNumber, ord.ConnectedDate
FROM [ORDER] ord
WHERE ord.ordertypeID = '2'
AND ord.ConnectedDate IS NOT NULL
)
SELECT cteOrderInfo.ConnectedDate, acc.DateUpgrade
FROM cteOrderInfo
INNER JOIN Laserbeak_Main.dbo.ACCOUNT_MPN acc
ON cteOrderInfo.AccountNumber = acc.AccountNumber
WHERE cteOrderInfo.ConnectedDate <> acc.DateUpgrade
SELECT Results Sample:
As Serge suggested, we did not have unique rows.
the solution we arrived at:
;WITH cteSourceStuff AS (
SELECT AccountNumber, MpnUpgrade, MAX(DateConnected) maxConnDate
FROM ORDER_DETAIL, [ORDER]
WHERE ORDER_DETAIL.OrderID = [ORDER].OrderID
AND LEN(MpnUpgrade) > 10
AND OrderTypeID = 2
GROUP BY AccountNumber, MpnUpgrade
)
UPDATE Laserbeak_Main.dbo.ACCOUNT_MPN set
DateUpgrade = cteSourceStuff.maxConnDate
FROM cteSourceStuff
WHERE cteSourceStuff.MpnUpgrade = ACCOUNT_MPN.Mpn
AND cteSourceStuff.AccountNumber = ACCOUNT_MPN.AccountNumber
AND DateUpgrade <> cteSourceStuff.maxConnDate
This works because the duplicates are initially removed, then we only update the rows that we are actually targeting. The reason we have issues before was that SQL was updating the 1st row it found, then when we re-ran or ran the select it was return rows matched on the key but that had not previously been updated.

Error: Subquery returned more than 1 value [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
The full error I get is:
Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I was passed by this SQL code that used to work in the past and I need to fix it, but I get the error above, but even if I comment out some parts the error stays the same
Here is the sql code:
SELECT
OrderId = OrdNameAdd.ORDERS_ID,
LTRIM(ISNULL(OrdNameAdd.OBY_FirstName, '') + ' ' + ISNULL(OrdNameAdd.OBY_LASTNAME, '')) AS OrderedByName,
ObyVar1 = (SELECT varfld_value FROM MAILERVBL WHERE OBYMAILER = MAILERVBL.MAILER_SEQID AND VARDEF_SEQUENCE = 1),
ObyVar2 = (SELECT varfld_value FROM MAILERVBL WHERE OBYMAILER = MAILERVBL.MAILER_SEQID AND VARDEF_SEQUENCE = 2),
ObyVar3 = (SELECT varfld_value FROM MAILERVBL WHERE OBYMAILER = MAILERVBL.MAILER_SEQID AND VARDEF_SEQUENCE = 3),
ExtendedDefaultValue = (SELECT sum(isnull(p.prduct_value,0) * (isnull(pickdt.prdord_toshipqty,1)))
FROM PICKDT
LEFT OUTER JOIN
locVerBals ON PICKDT.PRVERS_SEQID = locVerBals.PRVERS_Seqid
LEFT OUTER JOIN
LOCPRDSUM p ON locVerBals.PRDUCT_Seqid = p.PRDUCT_SEQID
AND p.system_id = PICPAK.SYSTEM_ID
WHERE
PICKDT.PICPAK_Seqid = PICPAK.PICPAK_Seqid
AND p.PRDUCT_INACTIVEDATE IS NULL),
FulfCharges = (rpt_BD.Linesshipped * ACCDEF_ChargePerLine) + ACCDEF_ChargePerShipment,
PubFreight = (rpt_BD.PubFreight),
TotalValue =
(SELECT
sum(isnull(p.prduct_value, 0) * (isnull(pickdt.prdord_toshipqty, 1)))
from PICKDT
LEFT OUTER JOIN locVerBals ON PICKDT.PRVERS_SEQID = locVerBals.PRVERS_Seqid
LEFT OUTER JOIN LOCPRDSUM p ON locVerBals.PRDUCT_Seqid = p.PRDUCT_SEQID
AND p.system_id = PICPAK.SYSTEM_ID
WHERE
PICKDT.PICPAK_Seqid = PICPAK.PICPAK_Seqid AND p.PRDUCT_INACTIVEDATE IS NULL)
+ isnull((rpt_BD.Linesshipped * ACCDEF_ChargePerLine), 0)
+ isnull(ACCDEF_ChargePerShipment,0) + isnull((rpt_BD.PubFreight), 0)
FROM
PICPAK
LEFT OUTER JOIN
ORDSTO ON PICPAK.ORDSTO_Seqid = ORDSTO.ORDSTO_Seqid
LEFT OUTER JOIN
OrdNameAdd ON ORDSTO.ORDERS_Seqid = OrdNameAdd.ORDERS_SEQID
LEFT OUTER JOIN
Rpt_BillingDetail rpt_BD ON PICPAK.PICPAK_Seqid = rpt_BD.PICPAK_Seqid
---------------hERE
WHERE
(convert(datetime, DateShipped, 1) >= '4/17/2012'
AND convert(datetime, DateShipped, 1) <= '12/17/2012')
---------------HERE
AND (PICPAK.PICPAK_Status = 'Complete' OR PICPAK.PICPAK_Status = 'Shipped'
OR picpak_Status = 'Voided')
/*AND (p.PRDUCT_INACTIVEDATE IS NULL)*/
AND ISNULL(PICPAK.SUPPLR_SEQID,0) = 0
GROUP BY
OrdNameAdd.ORDERS_ID,
OrdNameAdd.OBY_FirstName,
OrdNameAdd.OBY_LASTNAME,
OrdNameAdd.obymailer,
PICPAK.PICPAK_Seqid,
PICPAK.System_Id,
rpt_BD.PubFreight,
ACCDEF_ChargePerLine,
ACCDEF_ChargePerShipment,
rpt_BD.Linesshipped,
rpt_BD.Numpackages,
ordsto.orders_seqid
ORDER BY
ordsto.orders_seqid ASC
In your query, you have five subqueries for ObyVar1, ObyVar2, ObyVar3, ExtendedDefaultValue, and TotalValue.
The two value subqueries are using aggregations with no group by, so they should be returning one value.
Your problemis in the three ObyVars.
There are simple two ways to get rid of this:
Aggregate the values. So do max(varfld_value).
Choose one value. In SQL Server, this would be a top 1 (in other databases, it might be rownum = 1 or limit 1).
However, overall, I find select statements within select statements to be undesirable. I would replace those three variables with a subquery in the from clause:
(select mailer_seqid,
max(case when vardef_sequence = 1 then varfld_value end) as vv_1,
max(case when vardef_sequence = 2 then varfld_value end) as vv_2,
max(case when vardef_sequence = 3 then varfld_value end) as vv_3
from mailervbl
group by mailer_seqid
)
In most cases, this should be as or more efficient than the three subqueries.
I would suggest you to execute each sub query separately to find out which one is returning more than one record
If you have sub queries to SELECT columns Ex: (1) or with WHERE col = cluses Ex:(2) you should make sure only a single value is returned.
--Ex:(1) make sure only one row returned by the sub query,
--this case can be voided using TOP 1 from the sub query
SELECT col1, (SELECT colX from Table2 )
FROM Table1
--Ex:(2) this case can be avoided using IN instead =
SELECT col1, col2
FROM Table1
WHERE col3 = (SELECT colX from Table2 )
There seems no way we can identify them without having access your database, it's not advisable to write any where statement like this, not just talking about performance but also the problem you now facing.
To fix this you need either to go through the full logic and rewrite it with no sub-queries, or see if you can filter out some data via DISTINCT/TOP 1 in sub query without broke the logic itself. I suggest you rewrite it, sometimes it sounds complex but make things simpler.
You can't get a duplicate from the sub-queries where you're doing a single SUM statement so the problem is against the MAILERVBL table.
If you're ever looking for duplicates, run the following type of code to identify your duplicates:
select MAILER_SEQID, VARDEF_SEQUENCE, count(*) as numentries
from MAILERVBL
group by MAILER_SEQID, VARDEF_SEQUENCE
having count(*) > 1
order by numentries desc -- not really needed but useful to see where most of your duplicates are
Put whichever columns you are expecting to be unique in both your select and group by clauses.