Using self join/inner join to get the data by adding all the above rows data, in SQL Server - sql

I am working with SQL server, the query details are as below:
Need to get the calculative column whose result will be the addition of all the above rows. And I can't use correlated queries, Lag and Lead as it is not supported.
I tried using self-join/inner join/left outer join, the only problem I am facing is due to group by clause of other columns the result is not coming as expected.
For example, data is like
Expected Output
But the output I am getting due to group by clause applied on Column4.
Output getting is like below
Is there some alternative of GROUP BY clause or other alternatives?

In SQL Server 2012+, you would simply use cumulative sum:
select d.*, sum(column3) over (order by column2)
from data d;

using subquery for earlier version of 2012
SELECT Column1,Column2,Column3,
( SELECT SUM(y.Column3)
FROM Data y
WHERE y.Column1 = x.Column1
AND y.Column2 <= x.Column2
) AS [Column5(Summation of Column3)]
FROM Data x
ORDER BY 1 ,2 ,3;
Query result

It is resolved!!
Earlier my query was like,
SELECT a.*,
CASE WHEN col4!= A THEN SUM col3 ELSE 0 END
FROM a
GROUP BY col4, *...
This groupby was causing issue as it was giving the expected output
The things I changes in the query is,
SELECT a.*,
SUM(CASE WHEN col4!= A THEN col3 ELSE 0 END)
FROM a
GROUP BY (CASE WHEN col4!= A THEN col3 ELSE 0 END)
Now it is giving result as expected.
Thank you everyone for the help!!

Related

Why Using COALESCE or CASE keep returning null

I have the following SQL Query :
(SELECT ROUND(SUM(NBTOSUM)/1000000,1) FROM MyTable t2 WHERE t2.ELEMNAME IN ('A','B','C'))
Which works fine.
But Where there is no 'A','B','C' the result of the select is (null)
So to handle it, I did the following :
(SELECT COALESCE(ROUND(SUM(NBTOSUM)/1000000,1),0) FROM MyTable t2 WHERE t2.ELEMNAME IN ('A','B','C'))
And also try :
(SELECT
CASE
WHEN SUM(NBTOSUM)/1000000 IS NULL THEN 0
ELSE ROUND(SUM(NBTOSUM)/1000000,1)
END
FROM MyTable t2 WHERE t2.ELEMNAME IN ('A','B','C'))
But both keep returning null
What am I doing wrong ?
Move the WHERE restrictions to the CASE expression as well:
SELECT ROUND(SUM(CASE WHEN t2.ELEMNAME IN ('A','B','C')
THEN NBTOSUM ELSE 0 END) / 1000000, 1)
FROM MyTable t2;
Note that this trick solves the null problem and also avoids the need for an ugly COALESCE() call.
Your code should work as the SUM aggregation function will generate a single row of output regardless of whether the number of input rows is zero or non-zero. If there are no input rows or the values are all NULL then the output of the SUM will be NULL and then COALESCE would work.
Since you claim it does not then that suggests that there is something else going on in your query that you have not shared in the question.
You have braces around your statement suggesting that you are using it as part of a larger statement. If so, you can try moving the COALESCE to the outer query:
SELECT COALESCE(
(
SELECT ROUND(SUM(NBTOSUM)/1000000,1)
FROM MyTable
WHERE ELEMNAME IN ('A','B','C')
),
0
)
FROM your_outer_query;
That might fix the problem if you are somehow correlating to an outer query but your question makes no mention of that.
fiddle

sql group by satisfying multiple conditions within the group

I have a table like below:
I want to select the group which has RELB_CD =9093 and INFO_SRC_CD with 7784. Both conditions should be present in the group. In the table below my output should be the group with id=139993690.
You can use aggregation with having:
select id
from t
group by id
having sum(case when relb_cd = 9093 then 1 else 0 end) > 0 and
sum(case when info_src_cde = 7784 then 1 else 0 end) > 0
hey use this code hope this will help you.
you have to ignore the date column because that one is not allowing to group
select id,fisc_ind, sum(sls_amt),relb_cd,info_scop,info_src_cd from yourtable group by id,fisc_ind,relb_cd,info_scop,info_src_cd
Another working answer. If your data are large, you could compare both GL's and this working answer and see which runs faster for you. I honestly don't know which is faster. This was slightly faster with a very short set of data.
select id
from table1
where relb_cd = 9093
intersect
select id
from table1
where info_src_cd = 7784

Anyway to use IN operator in the SELECT statement? If not, why?

This may come off as a feature request more than anything, but it would be nice if SQL allowed use of the IN operator in a select statement such as the one below. I want to create new_variable intable1based on the ID variable in table2, hence the case statement.
select ID,
case when ID in (select ID
from table2)
then 1
else 0
end as new_variable
from table1
I understand that SQL will give me an error if I run this, but why is that the case? It doesn't seem obvious to me why SQL developers couldn't enable the IN operator to be used outside of the WHERE clause.
Side note: I'm currently using a left join to avoid this issue, so I am not hung up on this.
select ID,
case when ifnull(b.ID, 0) = 0 then 0
else 1
end as variable_name
from table1
left join(select ID from table2) as b
on a.ID = b.ID
SQL definitely supports this:
select ID,
(case when ID in (select ID from table2)
then 1 else 0
end) as new_variable
from table1
Note that there is a comma after id.
This is standard SQL. If your database doesn't support it, it is a feature request (and one that all or almost all databases support).

Subquery returned more than 1 value - error

I'm trying to make this query work but I can't understand what I am doing wrong. I saw other question with same problem but I did not understand anyway.
SELECT DoctorsVisits.VisitDate,
(SELECT COUNT(1) AS Total
FROM DoctorsVisits
WHERE (DoctorsVisits.PeriodOfVisitId=2)
GROUP BY DoctorsVisits.VisitDate) AS Manhas
FROM DoctorsVisits;
Are you sure you don't simply want a plain group by without sub-query?
SELECT DoctorsVisits.VisitDate, count(*) as Manhas
FROM DoctorsVisits
group by DoctorsVisits.VisitDate
Or perhaps:
SELECT DoctorsVisits.VisitDate,
sum(case when DoctorsVisits.PeriodOfVisitId=2 then 1 else 0 end) as Manhas
FROM DoctorsVisits
group by DoctorsVisits.VisitDate
You can just do the following. You're using an unnecessary sub-query for your COUNT.
SELECT DoctorsVisits.VisitDate, COUNT(*) As Total
FROM DoctorsVisits
WHERE DoctorsVisits.PeriodOfVisitId=2
GROUP BY DoctorsVisits.VisitDate

SQL Summing Multiple Joins

I shortened the code quite a bit, but hopefully someone will get the idea of what i am tryign to do. Need to sum totals from two different selects, i tried putting each of them in Left Outer Joins(tried Inner Joins too). If i run wiht either Left Outer Join commented out, I get the correct data, but when i run them together, i get really screwed up counts. So, i know joins are probably not the correct approach to summing data from the same table, i can;t simple do it in a where clause there is other table involved int he code i commented out.
I guess i am trying to sum together 2 different queries.
SELECT eeoc.EEOCode AS 'Test1',
SUM(eeosum.Col_One) AS 'Col_One',
FROM EEO1Analysis eeo
LEFT OUTER JOIN (
SELECT eeor.AnalysisID, eeor.Test1,
SUM(CASE eeor.ZZZ WHEN 1 THEN (CASE eeor.AAAA WHEN 1 THEN 1 ELSE 0 END) ELSE 0 END) AS 'Col_One',
FROM EEO1Roster eeor
..........
WHERE eeor.AnalysisID = 7
GROUP BY eeor.AnalysisID, eeor.EEOCode
) AS eeosum2 ON eeosum2.AnalysisID = eeo.AnalysisID
LEFT OUTER JOIN (
SELECT eeor.AnalysisID, eeor.Test1,
SUM(CASE eeor.ZZZ WHEN 1 THEN (CASE eeor.AAAA WHEN 1 THEN 1 ELSE 0 END) ELSE 0 END) AS 'Col_One',
FROM EEO1Roster eeor
........
) AS eeosum ON eeosum.AnalysisID = eeo.AnalysisID
WHERE eeo.AnalysisID = 7
GROUP BY eeoc.Test1
You could UNION ALL the 2 queries and then do a SUM + GROUP BY i.e.
SELECT Col1, Col2, SUM(Col_One) FROM
(SELECT Col1, Col2, SUM(Col_One)
FROM Table1
WHERE <Conditionset1>
GROUP BY Col1, Col2
UNION ALL
SELECT Col1, Col2, SUM(Col_One)
FROM Table1
WHERE <Conditionset2>
GROUP BY Col1, Col2)
GROUP BY
Col1, Col2
Of course, if there is are row(s) returned by and they would be double counted.
What about
SELECT ... FROM EEO1Analysis eeo,
(SELECT ... LEFT OUTER JOIN ... GROUP BY ... ) AS data
...
?
And, if you can, I'd recommend preparing the data to separate tables, then operate on them with different analysis IDs. Could save some execution time at least.
Need to sum totals from two different selects
If you expect one row single-column result, this way is enough
SELECT
((SELECT SUM(...) FROM ... GROUP BY...) +
(SELECT SUM(...) FROM ... GROUP BY...)) as TheSumOfTwoSums