split data in a table into 2 columns based on conditions - sql

got to split a column in my table into 2 based on conditions.All in a select clause.
my table has a column as detail_code. There are 2 detail codes .I want each detail code as a separate column in my select clause.
I tried subquery but it throws subquery returns more than one row.
select id,(select detail_code from detc where type_ind ='C')as Detail_code1,
(select detail_code from detc where type_ind ='P')as Detail_code2,
(Select sum(amount) from amount_tbl where detail_code in (select detail_code from detc where type_ind ='C')and term_code='2019')as amt_detail_code1
from id_table;
My output should be
Id Detail_code1 Detail_code2 sum(amt_Detail_Code1) sum(amt_Detail_code2)
1 C P 15 45
2 C P 785 74
My input
ID Detail_cd ind amt
317002687 CA20 C 3
317002687 CA21 C 60
317002687 CA23 C 18.75
317002687 CA25 C 179.64
317002687 CA26 C 136.5
317002687 CA27 C 8.25
317002687 CA28 C 4
317002687 CA2B C 8
317002687 CA2H C 6.75
317002687 CA2I C 237
317002687 CA2J C 65.4

This query would produce the output you describe:
SELECT id, 'C' AS detail_code1, 'P' AS detail_code2,
SUM(CASE WHEN ind = 'C' THEN amt END) AS sum_detail_code1,
SUM(CASE WHEN ind = 'P' THEN amt END) AS sum_detail_code2
FROM name_of_your_input_table
GROUP BY id;
Alternatively, since you know what the two detail codes are, you could make those the column names and have the value of each column be the average for that detail code. One way to do this is to pivot. Here's the Oracle syntax:
SELECT *
FROM (SELECT id, ind AS detail_code, amt
FROM name_of_your_input_table)
PIVOT (AVG(amt)
FOR detail_code IN ('C', 'P'));

Related

Sum a column based on a condition in another column with partitions

I'm trying to sum a column based on a condition in another column with partition by in SQL, but it's not working. So I hope somebody can help me with this.
My table is like this:
Group_1
Group_2
Date
Value
A
D
01/01/2021
1
A
D
01/02/2021
3
A
E
01/03/2021
5
B
D
01/01/2021
7
B
D
01/02/2021
9
B
E
01/03/2021
11
B
D
01/05/2021
17
B
D
01/03/2021
13
B
E
01/04/2021
13
C
D
01/01/2021
7
C
D
01/02/2021
10
So, I need to sum the values of [Value] for all rows where there is a 'D' on [Group_2] that is older than the first 'E' on the same group (if it exists) for each group of [Group_1].
And the result should be like:
Group_1
Group_2
Sum
A
D
4
B
D
16
C
D
17
Anybody knows how can I solve this kind of problem?
Try the following aggregation with NOT EXISTS:
SELECT Group_1, Group_2, SUM(Value) AS Value_Sum
FROM table_name T
WHERE Group_2 <> 'E' AND
NOT EXISTS (SELECT 1 FROM table_name D
WHERE D.Group_1 = T.Group_1 AND
D.Group_2 = 'E' AND
D.Date <= T.Date)
GROUP BY Group_1, Group_2
ORDER BY Group_1, Group_2
See a demo.
select group_1
,group_2
,sum(value)
from
(
select group_1
,group_2
,case when count(case when group_2 = 'E' then 1 end) over(partition by group_1 order by date) = 0 then value end as value
from t
) t
group by group_1, group_2
having group_2 = 'D'
group_1
group_2
sum
A
D
4
B
D
16
C
D
17
Fiddle

How to sum() if missing data in same column in SQL

I need to sum up the quantity according to typein the table below.
Table
Name Quantity Type
a 6 AB
b 2 BB
b 4 AB
c 8 BB
a 3 BB
b 5 AB
Outcome
Name AB_Type BB_Type
a 6 3
b 9 2
c 0 8
I am trying the below query but I can't get the numbers right.
SELECT S.Name, SUM(S1.Quantity) AS AB_Type, SUM(S2.Quantity) AS BB_Type
FROM Table AS S, Table AS S1, Table AS S2
WHERE S.Name = S1.SName = S2.Name AND S1.Type = 'AB'AND S2.Type = 'BB'
GROUP BY S.Name;
Thanks in advance!!
Try this
SELECT
Name,
SUM(CASE WHEN Type = 'AB' THEN Quantity ELSE 0 END) AS AB_Type,
SUM(CASE WHEN Type = 'BB' THEN Quantity ELSE 0 END) AS BB_Type
FROM Table
GROUP BY Name
you can use pivot as follows:
SELECT Name,
iif(AB_Type is null,0,AB_Type) AB_Type,
iif(BB_Type is null,0,BB_Type) BB_Type
FROM (
SELECT
Name
,Quantity
,CONCAT(Type, '_type') AS Col
FROM table
) Src
PIVOT (
sum(Quantity)
FOR Col IN (
[AB_Type], [BB_Type]
)
) Pvt

SELECT all rows where sum of count for this id is not 0

I'm querying an access db from excel. I have a table similar to this one:
id Product Count
1 A 0
1 B 5
3 C 0
2 A 0
2 B 0
2 C 5
3 A 6
3 B 5
3 C 7
From which I'd like to return all the rows (including the ones where count for that product is 0) where the sum of the count for this ID is not 0 and the product is either A or B. So from the above table, I would get:
id Product Count
1 A 0
1 B 5
3 A 6
3 B 5
The following query gives the right output, but is quite slow (takes almost a minute when querying from a somewhat small 7k row db), so I was wondering if there is a more efficient way of doing it.
SELECT *
FROM [BD$] BD
WHERE (BD.Product='A' or BD.Product='B')
AND BD.ID IN (
SELECT BD.ID
FROM [BD$] BD
WHERE (Product='A' or Product='B')
GROUP BY BD.ID
HAVING SUM(BD.Count)<>0)
Use your GROUP BY approach in a subquery and INNER JOIN that back to the [BD$] table.
SELECT BD2.*
FROM
(
SELECT BD1.ID
FROM [BD$] AS BD1
WHERE BD1.Product IN ('A','B')
GROUP BY BD1.ID
HAVING SUM(BD1.Count) > 0
) AS sub
INNER JOIN [BD$] AS BD2
ON sub.ID = BD2.ID;
IN() statement can perform badly a lot of times, you can try EXISTS() :
SELECT * FROM [BD$] BD
WHERE BD.Product in('A','B')
AND EXISTS(SELECT 1 FROM [BD$] BD2
WHERE BD.id = BD2.id
AND BD2.Product in('A','B')
AND BD2.Count > 0)
If you are looking for the records where the sum of the count for the id is non-zero, then at least one non-unique id must have a count that is non-zero.
SELECT *
FROM [BD$] BD
WHERE BD.Product IN ('A', 'B')
AND BD.ID IN (
SELECT DISTINCT b.ID
FROM [BD$] b
WHERE b.Product IN ('A', 'B')
AND b.Count<>0
)

How do I return the sum for this query?

I have the following tables I need to find out the sum.
Table A
ID Name
1 Jason
2 Peter
3 Ravi
Table B
ID ID_SEC
1 11
1 12
1 13
2 21
2 22
2 23
3 31
3 32
3 33
Table C
ID_SEC Value Include_Ind
11 100 Y
12 200 Y
13 300 N
21 10 Y
22 20 N
23 30 N
31 1000 N
32 2000 N
33 3000 N
Output
ID Name Total Include_Ind_count [only count when Y]
1 Jason 600 2
2 Peter 60 1
3 Ravi 6000 0
Use:
SELECT a.id,
a.name,
SUM(c.value) AS total
FROM TABLE_A a
JOIN TABLE_B b ON b.id = a.id
JOIN TABLE_C c ON c.id_sec = b.id_sec
GROUP BY a.id, a.name
The trick to counting INCLUDE_IND only when the flag is set to 'Y' is to use CASE() to test its value:
SQL> select a.id
2 , a.name
3 , sum ( c.val) as total
4 , count( case when c.include_ind = 'Y' then 1
5 else null end ) as inc_ind_cnt
6 from a
7 join b on ( b.id = a.id )
8 join c on ( c.id_sec = b.id_sec )
9 group by a.name, a.id
10 order by a.id
11 /
ID NAME TOTAL INC_IND_CNT
---------- ---------- ---------- -----------
1 Jason 600 2
2 Peter 60 1
3 Ravi 6000 0
SQL>
The ORDER BY is necessary to guarantee sort order since Oracle changed the algorithm it uses for GROUP BY operations in 10g.
You can use inner Joins and SUM for getting the result -
Assuming you tableC.Value is int field. Else you need to cast it.
SELECT tabA.id, tabA.name, SUM(tabC.value)
FROM TABLE_A tabA
INNER JOIN TABLE_B tabB ON tabB.id = tabA.id
INNER JOIN TABLE_C tabc ON tabC.id_sec = tabB.id_sec
GROUP BY tabA.id, tabA.name

SQL Query to sum fields from different tables

I'm a humble programmer that hates SQL ... :) Please help me with this query.
I have 4 tables, for example:
Table A:
Id Total
1 100
2 200
3 500
Table B
ExtId Amount
1 10
1 20
1 13
2 12
2 43
3 43
3 22
Table C
ExtId Amount
1 10
1 20
1 13
2 12
2 43
3 43
3 22
Table D
ExtId Amount
1 10
1 20
1 13
2 12
2 43
3 43
3 22
I need to make a SELECT that shows the Id, the Total and the SUM of the Amount fields of tables B, C and D like this
Id Total AmountB AmountC AmountD
1 100 43 43 43
2 200 55 55 55
3 500 65 65 65
I've tried with a inner join of the three tables by the Id and doing a sum of the amount fields but results are not rigth. Here is the wrong query:
SELECT dbo.A.Id, dbo.A.Total, SUM(dbo.B.Amount) AS Expr1, SUM(dbo.C.Amount) AS Expr2, SUM(dbo.D.Amount) AS Expr3
FROM dbo.A INNER JOIN
dbo.B ON dbo.A.Id = dbo.B.ExtId INNER JOIN
dbo.C ON dbo.A.Id = dbo.C.ExtId INNER JOIN
dbo.D ON dbo.A.Id = dbo.D.ExtId
GROUP BY dbo.A.Id, dbo.A.Total
Thanks in advance, its just that I hate SQL (or that SQL hates me).
EDIT: I had a typo. This query is not giving the right results. Extended the example.
Or you can take advantage of using SubQueries:
select A.ID, A.Total, b.SB as AmountB, c.SC as AmountC, d.SD as AmountD
from A
inner join (select ExtID, sum(Amount) as SB from B group by ExtID) b on A.ID = b.ExtID
inner join (select ExtID, sum(Amount) as SC from C group by ExtID) c on c.ExtID = A.ID
inner join (select ExtID, sum(Amount) as SD from D group by ExtID) d on d.ExtID = A.ID
From your description, this query should give you an error as you are using the non-existent column dbo.A.Amount in your group by. Changing this to dbo.A.Total might be what you need.
If you need all the amounts together, then try this query:
select A.Id, A.Total, sum(B.Amount + C.Amount + D.Amount) AS Total_Amount
from A
inner join B on A.Id = B.ExtId
inner join C on A.Id = C.ExtId
inner join D on A.Id = D.ExtId
group by A.Id, A.Total;
This one also works well
SELECT (SELECT SUM(Amount) FROM TableA) AS AmountA,
(SELECT SUM(Amount) FROM TableB) AS AmountB,
(SELECT SUM(Amount) FROM TableC) AS AmountC,
(SELECT SUM(Amount) FROM TableD) AS AmountD
This might help other users.
SELECT Total=(Select Sum(Amount) from table a)+(Select Sum(Amount) from table b)+(Select Sum(Amount) from table c)
Try this code
SELECT Total=isnull((Select Sum(Isnull(Amount,0)) from table a),0)+isnull((Select Sum(isnull(Amount,0)) from table b),0)+isnull((Select Sum(isnull(Amount,0)) from table c),0)