Teradata, subquery in case - sql

can you help me please. I need insert in case subquery, but teradata doesn't allow me this query, how can i change it (to similar query as case, like if)?
select amount, status
case
when max(amount) then
(select sum(a1.amount)+a2.amount
from payments a1
join payments a2 on a1.payment_id=a2.payment_id
where a2.status = 't'
and a1.status not like 'w'
group by a1.amount,a2.amount)
else sum(amount)
end
from payments
Amount | Status
--------| ------
10 | t
20 | w
30 | t
40 | w
50 | t
60 | t
70 | k
expected results: if amount is max then calculate amount to new column like sum(a1.amount)+a2.amount, where status for table a1 is 't' and status for a2 is not 'w'. If amount is not max, then just calculate all amounts from table payments.
results:
--for amount = 70 insert into new column (for example result) sum(all amount where status is not 'w') + sum(all amount where status is 't').
--For other amount < 70 insert into new column result sum(all amount).
Thank you for your help.

This will help I guess
select amt,status,(case when amt=max_amt then w_sum else total_sum end)results
from (
select amt,
status,
sum(amt) over(partition by (case when status='w' and status<>'t' then 1 else 0 end ))w_sum,
sum(amt) over(partition by 1) total_sum,
max(amt) over(partition by 1) max_amt
from t st)x
Let me know if it works for you.

Related

Join three tables with get sums of sales volume for each agent

I have table called PrimeClosureInformation and I want to get the sum of(Sales Volume) for each agentId and ExtraAgentId. I have some records have agentId and ExtraAgentId values, I want to Dividing (Sales Volume) on each agentId and ExtraAgentId then add each new value to both agentId and ExtraAgentId
This is the PrimeClosureInformation table I selected the sum of SaleValue for each AgentId my question is if I have ExtraAgentId value I want to Dividing the SaleValue on both for example in his table I want to get the SaleValue for mohamed and ahmed and if ahmed and mohamed both of them in the same record Dividing the SaleValue then add Divided value to his SaleValue
PrimeClosureInformationPK | SaleValue | AgentNames | AgentId | ExtraAgentId | ExtraAgentName
1 | 3802500.00 | mohamed | 80994 | 81009 | ahmed
2 | 2145500.00 | ahmed | 98751 | 0 |
This is the select statement I was write it but this query is select sum of SaleValue for each AgentId only
SELECT DISTINCT sum(SaleValue)as SalesVolume, AgentNames
FROM [dbo].[PrimeClosureInformation], VW_User
where VW_User.FullName = AgentNames
AND VW_User.UserIdLG = PrimeClosureInformation.AgentId
AND VW_User.Status= N'active'
GROUP BY AgentNames
Use UNION ALL to return all Agents (primary and extra) with their corresponding sales:
SELECT SUM(t.volume) as SalesVolume, t.AgentName
FROM (
SELECT AgentID, AgentNames AS AgentName,
SaleValue / CASE WHEN COALESCE(ExtraAgentID, 0) <> 0 THEN 2 ELSE 1 END volume
FROM [dbo].[PrimeClosureInformation]
UNION ALL
SELECT ExtraAgentID, ExtraAgentName, SaleValue / 2
FROM [dbo].[PrimeClosureInformation]
WHERE COALESCE(ExtraAgentID, 0) <> 0
) AS t INNER JOIN VW_User AS u
ON u.UserIdLG = t.AgentId
WHERE u.Status = N'active'
GROUP BY t.AgentName
You can unpivot the data using cross apply and then aggregation:
SELECT v.agentname, sum(SaleValue * factor) as SalesVolume
FROM [dbo].PrimeClosureInformation pci CROSS APPLY
(VALUES (AgentNames, AgentId, case when ExtraAgentId > 0 then 1.0 else 0.5 end),
(ExtraAgentId, ExtraAgentName, case when ExtraAgentId > 0 then 0.5 else 0.0 end)
) v(AgentName, AgentId, factor) join
VW_User
ON u.FullName = v.AgentName AND
u.UserIdLG = v.AgentId AND
u.Status = N'active'
GROUP BY v.AgentName

condense results into 1 result under a certain limit

So, I have a result set that has a percentage of the total in 1 column and a name in the other column.
So for example -
Name | Percentage
Jill | 12
Sam | 24
Steve| 2
Jeff | 3
Elvis | 59
I am trying to condense any result thats less than 15% into on row,
so my result would be
Name | Percentage
Everyone else| 17
Sam | 24
Elvis | 59
Thanks!
You can use APPLY :
SELECT tt.Name, SUM([Percentage]) AS [Percentage]
FROM table t CROSS APPLY
( VALUES (CASE WHEN [Percentage] < 15
THEN 'Everyone else'
ELSE Name
END)
) tt(Name)
GROUP BY tt.Name;
Use a case expression in a derived table (the sub-query) to put all less than 15% people together. GROUP BY its result:
select name, sum(Percentage)
from
(
select case when Percentage > 15 then name
else 'Everyone else'
end as name,
Percentage
from tablename
) dt
group by name
For such a simple condition, you can just use CASE expressions:
select (case when percentage < 15 then 'Everyone else'
else name
end) as name,
sum(percentage) as percentage
from t
group by (case when percentage < 15 then 'Everyone else'
else name
end)
order by sum(percentage) asc;

Calculate product of column values on the basis of other column in SQL Server

I have a table
Tid Did value
------------------
1 123 100
1 234 200
2 123 323
2 234 233
All tids have dids as 123 and 234. So for every tid having dids 123 and 234 I want the product of corresponding values
The output table will be
Tid Product
------------------
1 20000 (product of 100 and 200)
2 75259 (product of 323 and 233)
Any help?
select tid,
min(case when did = 123 then value end)
* min(case when did = 234 then value end) product
from my_table
group by tid
To get the data for multiple rows combined (based on tid) you use GROUP BY.
Because you're grouping by tid, you have to use an aggregate function to do anything with other values from the individual rows. If implied assumptions hold (exactly 1 row matching each did for each tid) then it doesn't matter much what aggregate function you use; min is as good as anything.
Within the aggregation, you use CASE logic to select value for the required did (and NULL for all other rows in the tid group).
Then just do the math.
You can use some arithmetic to get the product per tid.
select tid,exp(sum(log(value))) as prod
from t
group by tid
To do this only for tid's having did values 123 and 234, use
select tid,exp(sum(log(value))) as prod
from t
group by tid
having count(distinct case when did in (123,234) then did end) = 2
Here's a Rexster solution, based on good work of #gbn here
SELECT
Tid,
CASE
WHEN MinVal = 0 THEN 0
WHEN Neg % 2 = 1 THEN -1 * EXP(ABSMult)
ELSE EXP(ABSMult)
END
FROM
(
SELECT
Tid,
SUM(LOG(ABS(NULLIF(value, 0)))) AS ABSMult,
SUM(SIGN(CASE WHEN value < 0 THEN 1 ELSE 0 END)) AS Neg,
MIN(ABS(value)) AS MinVal
FROM
t
GROUP BY
Tid
) t2

SQL: Column Sum

Lets have following sample table:
Person Quantity
A 1
B 2
C 3
D 4
E 5
Result should be:
PersonAggregate
1 (0+Quantity of PersonA)=sumA
3 (sumA+Quantity of PersonB)=sumB
6 (sumB+Quantity of PersonC)=sumC
10 (sumC+Quantity of PersonD)=sumD
15 (sumD+Quantity of PersonE)
Is it possible to get this result in onq SQL-query?
Most versions of SQL support cumulative sums as a window function:
select person, sum(quantity) over (order by person) as cumesum
from sample;
You can can also do this with a correlated subquery:
select s.person,
(select sum(s2.quantity)
from samples s2
where s2.person <= s.person
) as cumesum
from sample s;
this will obviously get the individual sums.
select person, sum(quantity)
from sample
group by person
order by person
i don't think your desired effect can be done in a set based way. a procedural language with cursor, like T-SQL or PLSQL, can do it easily.
i'd write a stored procedure and call it.
If the sample table has more than one row per person with multiple quantities that need to be summed you could use:
select curr.person, curr.sum_person + case when prev.person <> curr.person
then prev.sum_person
else 0 end as person_sum
from (select person, sum(quantity) as sum_person
from sample
group by person) curr
cross join (select person, sum(quantity) as sum_person
from sample
group by person) prev
where prev.person =
(select max(x.person) from sample x where x.person < curr.person)
or curr.person = (select min(person) from sample)
group by curr.person
Fiddle: http://sqlfiddle.com/#!2/7c3135/6/0
Output:
| PERSON | PERSON_SUM |
|--------|------------|
| A | 1 |
| B | 3 |
| C | 5 |
| D | 7 |
| E | 9 |
If there is only one row per person on the sample table, you could more simply use:
select curr.person, curr.quantity + case when prev.person <> curr.person
then prev.quantity
else 0 end as person_sum
from sample curr
cross join sample prev
where prev.person =
(select max(x.person) from sample x where x.person < curr.person)
or curr.person = (select min(person) from sample)
group by curr.person
Fiddle: http://sqlfiddle.com/#!2/7c3135/8/0
Output returned is the same, because in your example, there is only one row per person.
If using Oracle, SQL Server, or a database that supports analytic functions, you could use:
If sample has one row per person:
select person,
sum(quantity) over(order by person rows between 1 preceding and current row) as your_sum
from sample
order by person
Fiddle: http://sqlfiddle.com/#!4/82e6f/1/0
If sample has 2+ rows per person:
select person,
sum(sum_person) over(order by person rows between 1 preceding and current row) as your_sum
from (select person, sum(quantity) as sum_person
from sample
group by person) x
order by person
Fiddle: http://sqlfiddle.com/#!4/82e6f/4/0

Update column value of one row from other rows

I have the following table:
sno name pid amount total
1 Arif 0 100 null
2 Raj 1 200 null
3 Ramesh 2 100 null
4 Pooja 2 100 null
5 Swati 3 200 null
6 King 4 100 null
I want total of each person such that it gives total sum of amount of its descendants.
For ex.
for RAJ total will be : total= amount of(raj+ramesh+pooja+swati+king)
for SWATI :Total=amount of swati only.
You could try something like this:
WITH hierarchified AS (
SELECT
sno,
amount,
hierarchyID = CAST(sno AS varchar(500))
FROM yourTable
WHERE pid = 0
UNION ALL
SELECT
t.sno,
t.amount,
hierarchyID = CAST(h.hierarchyID + '/' + RTRIM(t.sno) AS varchar(500))
FROM yourTable t
INNER JOIN hierarchified h ON t.pid = h.sno
)
UPDATE yourTable
SET total = t.amount + ISNULL(
(
SELECT SUM(amount)
FROM hierarchified
WHERE hierarchyID LIKE h.hierarchyID + '/%'
),
0
)
FROM yourTable t
INNER JOIN hierarchified h ON t.sno = h.sno;
Note that this query (which you can try on SQL Fiddle) would probably not be very efficient on a large dataset. It might do as a one-off query, and then it would likely be better to organise updating the totals each time the table is updated, i.e. using triggers.