Update with aggregate - sql

I'm having trouble changing an update from Oracle to SQL Server
I have doubt in an update in SQL Server. In Oracle, I managed to do it, but in SQL Server, I'm not getting it.
Below are the two examples (Oracle worked, however SQL Server returns the error:
An aggregate may not appear in the list of sets of an UPDATE statement.
Oracle
UPDATE
tab1
SET
(t1.va, t1.vb) = (
SELECT
sum(
CASE
WHEN (t2.date2 - t2.date1) <= 30 THEN Coalesce((t2.x + t2.y), 0)
END
) * 100,
sum(
CASE
WHEN (t2.date2 - t2.date1) <= 60
AND (t2.date2 - t2.date1) > 30 THEN Coalesce((t2.y + t2.z), 0)
END
) * 100
FROM
tab2 t2
WHERE
t2.cd_xyz = tab1.cd_xyz
);
SQL Server
UPDATE
tab1 t1
SET
t1.va = sum(
CASE
WHEN (t2.date2 - t2.date1) <= 30 THEN COALESCE((t2.x + t2.y), 0)
END
) * 100,
t1.vb = sum(
CASE
WHEN (t2.date2 - t2.date1) <= 60
AND (t2.date2 - t2.date1) > 30 THEN COALESCE((t2.y + t2.z), 0)
END
) * 100
FROM
tab2 t2
INNER JOIN tab1 t1 ON t2.cd_xyz = t1.cd_xyz;

You need to calculate the values you want to use in a sub-query then join then onto the table you are updating using the UPDATE ... FROM syntax from the documentation.
I'm not totally sure I've expressed your logic correctly given you didn't have any grouping, but did have a sum, but it should be enough to get you started.
UPDATE tab1 SET
va = t2a.vaNew
, vb = t2a.vbNew
FROM tab1
INNER JOIN (
SELECT
cd_xyz
, SUM(
CASE
WHEN (t2.date2 - t2.date1) <= 30 THEN COALESCE((t2.x + t2.y), 0)
END
) * 100 as vaNew
, SUM(
CASE
WHEN (t2.date2 - t2.date1) <= 60
AND (t2.date2 - t2.date1) > 30 THEN COALESCE((t2.y + t2.z), 0)
END
) * 100 AS vbNew
FROM tab2 t2
GROUP BY cd_xyz
) AS t2a ON t2a.cd_xyz = t1.cd_xyz;

Related

Nested case statement - what's is wrong with it?

I want to write a nested case statement where i want in Microsoft SQL Server that
case
when date 2 is null
then date 1
else date 2
end ---1st condition
and use this condition as:
case
when condition1 is <= getdate()
and condition1 < getdate() + 14
then 'DUE'
else 'after .
I am getting error message and not able to complete my case statement.
you don't need the 1st check because both the checks are comparing getdate
case when isnull([date 1],[date 2]) <= getdate() + 14 then 'DUE' else <'' end
I would use CROSS APPLY for this :
SELECT t2.y
FROM sometable
CROSS APPLY (SELECT CASE WHEN date 2 IS NULL THEN date 1 ELSE date 2 END) t1(x)
CROSS APPLY (SELECT CASE WHEN t1.x <= getdate() AND t1.x < getdate() + 14 THEN 'DUE' ELSE 'AFTER' END) t2(y)
Note that you can use COALESCE to make the first CROSS APPLY expression simpler, and IIF for the second :
SELECT t2.y
FROM sometable
CROSS APPLY (SELECT COALESCE(date 2, date 1)) t1(x)
CROSS APPLY (SELECT IIF(t1.x <= getdate() AND t1.x < getdate() + 14, 'DUE', 'AFTER')) t2(y)

How can I get different data with case?

In view If lokasyonno= 27 , I want the first block to run, if not the second block. How can I do it?
I tried to do it with the switch case structure, but I couldn't get a result because there is no common column.
FIRST
SELECT round(UH.NETTUTAR)
FROM TBL_IRSALIYE IR
INNER JOIN TBL_URUNHAREKETLERI UH ON UH.IRSALIYEID = IR.IRSALIYEID
INNER JOIN TBL_URUNLER U ON UH.URUNID = U.URUNID
WHERE IR.LOKASYONNO = 27
AND IR.TUR = 7
AND IR.IPTAL = 0
AND IR.ONAY = 1
AND IR.BILLED = 1
AND IR.INTERNET = 60
AND ROWNUM <= 10
AND IR.TARIH > TO_DATE ('2020-09-27 ', 'yyyy-mm-dd ')
AND IR.TARIH <= TO_DATE ('2020-10-05', 'yyyy-mm-dd ')
second
NVL (
(SELECT ROUND (
SUM (
CASE DOCUMENT_TYPE
WHEN 2
THEN
(CASE TRANSACTION_TYPE
WHEN 0
THEN
0
- ( LINE_TOTAL_VALUE
- LINE_TOTL_DISCOUNT)
ELSE
LINE_TOTAL_VALUE
- LINE_TOTL_DISCOUNT
END)
ELSE
(CASE TRANSACTION_TYPE
WHEN 1
THEN
0
- ( LINE_TOTAL_VALUE
- LINE_TOTL_DISCOUNT)
ELSE
( LINE_TOTAL_VALUE
- LINE_TOTL_DISCOUNT)
END)
END),
10)
FROM TBL_TRANSACTION_LINES
WHERE (TRANSACTION_TYPE NOT IN (10, 30))
AND STORE_NO = LOK.LOKASYONNO
AND (URUNID = TBL_URUNLER.URUNID)
AND TRANSACTION_DATE >
TO_DATE ('2020-09-27 0:0:0',
'yyyy-mm-dd HH24:MI:SS')
AND TRANSACTION_DATE <=
TO_DATE ('2020-10-04 0:0:0',
'yyyy-mm-dd HH24:MI:SS')),
0)
AS HAFTALIKKASASATISTUTARI
Use a union of the two queries but add a not exists() on the first query as an additional condition of the second query:
<first query>
union all
<second query>
where not exists (<first query>)

How to merge two SQL SELECTqueries into one query in SQL Server CE?

I have two SELECT queries, those return more than 45 and less than 45. I need to merge these 2 queries into one. If it is possible, how can I achieve it?
Query 1:
SELECT
SUM(tbl_invoices.pendingamount) AS morethan45
FROM
tbl_debit
INNER JOIN
tbl_invoices ON tbl_debit.invoice = tbl_invoices.invoice
WHERE
(tbl_invoices.state = - 1)
AND (DATEDIFF(day, tbl_debit.purchasedate, GETDATE()) >= 45)
Query 2:
SELECT
SUM(tbl_invoices.pendingamount) AS lessthan45
FROM
tbl_debit
INNER JOIN
tbl_invoices ON tbl_debit.invoice = tbl_invoices.invoice
WHERE
(tbl_invoices.state = - 1)
AND (DATEDIFF(day, tbl_debit.purchasedate, GETDATE()) < 45)
I tried following query but it returns an error.
SELECT (Query 1),(Query 2)
Please help me to solve this issue.
You should be able to use CASE, something like;
SELECT
SUM(CASE WHEN (DATEDIFF(day, tbl_debit.purchasedate, GETDATE()) >= 45)
THEN tbl_invoices.pendingamount ELSE 0 END) AS morethan45,
SUM(CASE WHEN (DATEDIFF(day, tbl_debit.purchasedate, GETDATE()) < 45)
THEN tbl_invoices.pendingamount ELSE 0 END) AS lessthan45
FROM tbl_debit
INNER JOIN tbl_invoices
ON tbl_debit.invoice = tbl_invoices.invoice
WHERE (tbl_invoices.state = - 1)

Multiple Calculations in case statement not running

I am trying to run a query that obtains an average for two different variables then calculates the difference between them. However, the I keep getting an error that the query doesn't recognize the variable names in the second calculation. I have been looking around but I feel like I am just missing a simple step here
Here is the full query
select
DATEPART(dw,t1.Date),
DATENAME(dw,t1.Date),
AVG (CASE WHEN (rraw.Mode='Passive') THEN T1.LengthSec + T1.Sec ELSE NULL
END) AS 'Passive',
AVG (CASE WHEN (rraw.Mode='Active') THEN T1.Sec + T1.Sec ELSE NULL
END) AS 'Active'
then ( Passive - Active ) / Passive * 100.0 AS 'ModePrctDiff'
from bm.t1agent t1 with (nolock)
JOIN prc.Request rreq
on t1.id = rreq.t1ID
join PRC.Raw rraw with (nolock)
on rreq.ID = rraw.Id
where t1.Date >= '2014-12-07'
GROUP BY ROLLUP ((DATEPART(dw,t1.Date),DATENAME(dw,t1.Date)))
The error is occurring on the then statement. If I run it without that part, I obtain these results
Day Of Week Passive Active
Sunday 350.54 370.54
Monday 365.54 380.91
I want to have the results read
Day Of Week Passive Active Difference
Sunday 350.54 370.54 xxxx
Monday 365.54 380.91 xxxx
you can't use the alias name given to a column in the same select clause
you need to write it as a subquery or cte.
with cte
as
(
select
DATEPART(dw,t1.Date) as dw1,
DATENAME(dw,t1.Date) as dw2,
AVG (CASE WHEN (rraw.Mode='Passive') THEN T1.LengthSec + T1.Sec ELSE NULL
END) AS 'Passive',
AVG (CASE WHEN (rraw.Mode='Active') THEN T1.Sec + T1.Sec ELSE NULL
END) AS 'Active'
from bm.t1agent t1 with (nolock)
JOIN prc.Request rreq
on t1.id = rreq.t1ID
join PRC.Raw rraw with (nolock)
on rreq.ID = rraw.Id
where t1.Date >= '2014-12-07'
GROUP BY ROLLUP ((DATEPART(dw,t1.Date),DATENAME(dw,t1.Date)))
)
select * , ( Passive - Active ) / Passive * 100.0 AS 'ModePrctDiff'
from cte

SQL: Filtering a query with multiple conditions

As I'm sure you'll be able to tell from this question, I am very new and unfamiliar with SQL. After quite some time (and some help from this wonderful website) I was able to create a query that lists almost exactly what I want:
Select p1.user.Office,
p1.user.Loc_No,
p1.user.Name,
p1.user.Code,
p1.user.Default_Freq,
(Select distinct MAX(p2.pay.Paycheck_PayDate)
from p2.pay
where p1.user.Client_TAS_CL_UNIQUE = p2.pay.CL_UniqueID) as Last_Paycheck
from
PR.client
where
p1.user.Client_End_Date is null
and p1.user.Client_Region = 'Z'
and p1.user.Client_Office <> 'ZF'
and substring(p1.user. Code,2,1) <> '0'
Now I just need to filter this slightly more using the following logic:
If Default_Freq = 'W' then only output clients with a Last_Paycheck 7 or more days past the current date
If Default_Freq = 'B' then only output clients with a Last_Paycheck 14 or more days past the current date
Etc., Etc.
I know this is possible, but I have no clue how the syntax should start. I believe I would need to use a Case statement inside the Where clause? Any help is greatly appreciated as always!
SELECT
X.p1.user.Office,
X.p1.user.Loc_No,
X.p1.user.Name,
X.p1.user.Code,
X.Default_Freq,
X.Last_Paycheck
FROM
(Select
p1.user.Office,
p1.user.Loc_No,
p1.user.Name,
p1.user.Code,
p1.user.Default_Freq AS Default_Freq,
(Select distinct MAX(p2.pay.Paycheck_PayDate)
from p2.pay
where p1.user.Client_TAS_CL_UNIQUE = p2.pay.CL_UniqueID) as Last_Paycheck
from
PR.client
where
p1.user.Client_End_Date is null
and p1.user.Client_Region = 'Z'
and p1.user.Client_Office <> 'ZF'
and substring(p1.user. Code,2,1) <> '0') X
WHERE (
(X.Default_Freq = 'W' AND (DATEDIFF ( d , X.Last_Paycheck , #currentDate) >= 7))
OR (X.Default_Freq = 'B' AND (DATEDIFF ( d , X.Last_Paycheck , #currentDate) >= 14))
)
Use your current query as a derived table or a CTE (CTEs exists for SQL Server 2005+). And then you can do:
;WITH CTE AS
(
--- Your current query here
)
SELECT *
FROM CTE
WHERE (Default_Freq = 'W' AND DATEDIFF(DAY,Last_Paycheck,GETDATE()) >= 7)
OR (Default_Freq = 'B' AND DATEDIFF(DAY,Last_Paycheck,GETDATE()) >= 14)
OR () -- keep going
Make a case statement, and put that in your where clause.
I.e. (off the top of my head):
CASE
WHEN (Default_Freq = 'W' AND DATEDIFF(DAY,Last_Paycheck,GETDATE()) >= 7) THEN 1
WHEN (Default_Freq = 'B' AND DATEDIFF(DAY,Last_Paycheck,GETDATE()) >= 14) THEN 1
ELSE 0 END = 1
try this with inner query:
select * from (
Select
p1.user.Office,
p1.user.Loc_No,
p1.user.Name,
p1.user.Code,
p1.user.Default_Freq,
(Select distinct MAX(p2.pay.Paycheck_PayDate)
from p2.pay
where p1.user.Client_TAS_CL_UNIQUE = p2.pay.CL_UniqueID) as Last_Paycheck
from PR.client
where p1.user.Client_End_Date is null
and p1.user.Client_Region = 'Z'
and p1.user.Client_Office <> 'ZF'
and substring(p1.user. Code,2,1) <> '0') t
where (
(Default_Freq = 'W' AND (DATEDIFF ( d , Last_Paycheck , #currentDate) <= 7))
OR (Default_Freq = 'B' AND (DATEDIFF ( d , Last_Paycheck , #currentDate) <= 14))
)