does anyone know how to sum and subtract from aggregate values of a group? I have Groups 1,2, and 3 with Amounts. I want to take the sum of Group 1 and subtract it by the sum of Group 2 in a row outside the main row grouping. I've used IF statements and looked all over as well as tested everything i can think of. Can anyone shed light how to do this?
DataSet1
Fields: "Group", "Amounts"
Note: SQL is not an option because i have a column grouping across the top as well.
I don't know what you mean by "outside the main row grouping." Could you provide an example?
From your description (less the one hedge factor I just mentioned), it looks like all you need to do is this:
select <whatever>, Sum( Field1 ) as Group1, Sum( Field2 ) as Group2,
Sum( Field1 ) - Sum( Field2 ) as FinalAmount
from ...
Edit: So you have an actual column called "Group" and you want sums of each group designated by the value of that column. That's easy to do.
select Group,
Sum( case Group when 1 then Amount else 0 end ) as Group1,
Sum( case Group when 2 then Amount else 0 end ) as Group2,
Sum( case Group when 3 then Amount else 0 end ) as Group3
from ...
If you want to do further processing between the group totals, I would suggest CTE or derived/inline view.
Related
To solve the below question, I want to combine 2 result sets (Query #1 + Query #2) using SQL.
I've tried UNION but it didn't work. Help!
Question:
Sample Data:
Query #1:
SELECT
COUNT(student_id),
MAX(registration_date),
MAX(lab1)
FROM grades;
Query #1 result:
Query #2:
SELECT
MAX(SUM(NVL(lab1, 0) + NVL(lab2, 0)))
FROM grades
GROUP BY student_id;
Query #2 result:
You had a few descent attempts. If you could edit your existing post and supply some sample data would help better show us what the underlying basis would be. Are there multiple rows per lab1 and/or lab2. Are there multiple classes represented? You want a sum, but doing a max?
You need a group by per student so each student shows of their own. So you had that. You also had max(), but also sum(). So hopefully this will be close to what you need.
SELECT
g.student_id,
max( g.registration_date ) NewestRegistrationDate,
max( coalesce( g.lab1, 0 )) HighestLab1,
max( coalesce( g.lab2, 0 )) HighestLab2,
max( coalesce( g.lab1, 0 ))
+ max( coalesce( g.lab2, 0 )) HighestBothLabs
FROM
grades g
group by
g.student_id
At least the above will give you the per-student basis as your grid image would represent, not the final answer which apparently wants the total student and the highest grade overall. That one, you WOULD want the count(), and ignore the group by as you want the answer over the entire set. But do you want the highest in each lab category? Or the highest per student with whatever the highest student's total labs are.
EX:
Student Lab1 Lab2 Total
1 75 92 167
2 74 100 174
Here, you have two students. The first has the highest lab1, but the second has highest total. You need to make that determination or at least get clarification from the teacher. If you want the highest by lab 1, you probably need something like wrapping the first query into the second. But that too may be over what you are learning. Using one result as basis for the outer such as.
select
count(*) TotalStudents,
Max( PerStudent.NewestRegistrationDate ) MostRecentRegistrationDate,
Max( PerStudent.HighestLab1 ) HighestFirstLab,
Max( PerStudent.HighestBothLabs ) HighestAllLabs
from
( SELECT
g.student_id,
max( g.registration_date ) NewestRegistrationDate,
max( coalesce( g.lab1, 0 )) HighestLab1,
max( coalesce( g.lab2, 0 )) HighestLab2,
max( coalesce( g.lab1, 0 ))
+ max( coalesce( g.lab2, 0 )) HighestBothLabs
FROM
grades g
group by
g.student_id ) PerStudent
The inner pre-query (alias PerStudent) keeps the data at the per-student level giving you the basis to get the highest per at the OUTER query level that does NOT have the group by. But at least running the first query to confirm the baseline of the data first. If you dont have that correct, the outer won't make sense either.
Thanks to DRapp, I solved it with the code below.
SELECT
COUNT(*) TotalStudents,
MAX(PerStudent.MostRecentRegistrationDate) MostRecentRegistrationDate,
MAX(PerStudent.HighestFirstLab) HighestFirstLab,
MAX(PerStudent.SumBothLabs) HighestBothLabs
FROM
(SELECT
MAX(g.registration_date) MostRecentRegistrationDate,
MAX(coalesce(g.lab1, 0)) HighestFirstLab,
SUM(coalesce(g.lab1, 0) + coalesce(g.lab2, 0)) SumBothLabs
FROM grades g
GROUP BY g.student_id) PerStudent;
I am pretty much stuck with a problem I am facing with SQL Server. I want to show in a query the amount of times that specific value occurs. This is pretty easy to do, but I want to take it a step further and I think the best way to explain on what I am trying to achieve is to explain it using images.
I have two tables:
Plant and
Chest
As you can see with the chest the column 'hoeveelheid' tells how full the chest is, 'vol' == 1 and 3/4 is == 0,75. In the plant table there is a column 'Hoeveelheidperkist' which tells how much plants there can be in 1 chest.
select DISTINCT kist.Plantnaam, kist.Plantmaat, count(*) AS 'Amount'
from kist
group by kist.plantnaam, kist.Plantmaat
This query counts all the chests, but it does not seperate the count of 'Vol' chests and '3/4' chests. It only does This. What I want to achieve is this. But I have no idea how. Any help would be much appreciated.
If you use group by you don't need distinct
and if you want the seprated count for hoeveelheid you ust add to the group by clause
select DISTINCT kist.Plantnaam, kist.Plantmaat, kist.hoeveelheid, count(*) AS 'Amount'
from kist
group by kist.plantnaam, kist.Plantmaat, hoeveelheid
or if you want all the 3 count ond the samw rowx you could use a condition aggreagtion eg:
select DISTINCT kist.Plantnaam, kist.Plantmaat
, sum(case when kist.hoeveelheid ='Vol' then 1 else 0 end) vol
, sum(case when kist.hoeveelheid ='3/3' then 1 else 0 end) 3_4
, count(*) AS 'Amount'
from kist
group by kist.plantnaam, kist.Plantmaat
When you want to filter the data on the counts you have to use having clause. When ever you are using aggregate functions(sum, count, min, max) and you want to filter them on aggregation basis, use having clause
select DISTINCT kist.Plantnaam, kist.Plantmaat, count(*) AS 'Amount'
from kist
group by kist.plantnaam, kist.Plantmaat having count(*) = 1 -- or provide necessary conditions
I am using SQL Server and wondering if it is possible to iterate through time series data until specific condition is met and based on that label my data in other table?
For example, let's say I have a table like this:
Id Date Some_kind_of_event
+--+----------+------------------
1 |2018-01-01|dsdf...
1 |2018-01-06|sdfs...
1 |2018-01-29|fsdfs...
2 |2018-05-10|sdfs...
2 |2018-05-11|fgdf...
2 |2018-05-12|asda...
3 |2018-02-15|sgsd...
3 |2018-02-16|rgw...
3 |2018-02-17|sgs...
3 |2018-02-28|sgs...
What I want to get, is to calculate for each key the difference between two adjacent events and find out if there exists difference > 10 days between these two adjacent events. In case yes, I want to stop iterating for that specific key and put label 'inactive', otherwise 'active' in my other table. After we finish with one key, we start with another.
So for example id = 1 would get label 'inactive' because there exists two dates which have difference bigger that 10 days. The final result would be like that:
Id Label
+--+----------+
1 |inactive
2 |active
3 |inactive
Any ideas how to do that? Is it possible to do it with SQL?
When working with a DBMS you need to get away from the idea of thinking iteratively. Instead you need to try and think in sets. "Instead of thinking about what you want to do to a row, think about what you want to do to a column."
If I understand correctly, is this what you're after?
CREATE TABLE SomeEvent (ID int, EventDate date, EventName varchar(10));
INSERT INTO SomeEvent
VALUES (1,'20180101','dsdf...'),
(1,'20180106','sdfs...'),
(1,'20180129','fsdfs..'),
(2,'20180510','sdfs...'),
(2,'20180511','fgdf...'),
(2,'20180512','asda...'),
(3,'20180215','sgsd...'),
(3,'20180216','rgw....'),
(3,'20180217','sgs....'),
(3,'20180228','sgs....');
GO
WITH Gaps AS(
SELECT *,
DATEDIFF(DAY,LAG(EventDate) OVER (PARTITION BY ID ORDER BY EventDate),EventDate) AS EventGap
FROM SomeEvent)
SELECT ID,
CASE WHEN MAX(EventGap) > 10 THEN 'inactive' ELSE 'active' END AS Label
FROM Gaps
GROUP BY ID
ORDER BY ID;
GO
DROP TABLE SomeEvent;
GO
This assumes you are using SQL Server 2012+, as it uses the LAG function, and SQL Server 2008 has less than 12 months of any kind of support.
Try this. Note, replace #MyTable with your actual table.
WITH Diffs AS (
SELECT
Id
,DATEDIFF(DAY,[Date],LEAD([Date],1,0) OVER (ORDER BY [Id], [Date])) Diff
FROM #MyTable)
SELECT
Id
,CASE WHEN MAX(Diff) > 10 THEN 'Inactive' ELSE 'Active' END
FROM Diffs
GROUP BY Id
Just to share another approach (without a CTE).
SELECT
ID
, CASE WHEN SUM(TotalDays) = (MAX(CNT) - 1) THEN 'Active' ELSE 'Inactive' END Label
FROM (
SELECT
ID
, EventDate
, CASE WHEN DATEDIFF(DAY, EventDate, LEAD(EventDate) OVER(PARTITION BY ID ORDER BY EventDate)) < 10 THEN 1 ELSE 0 END TotalDays
, COUNT(ID) OVER(PARTITION BY ID) CNT
FROM EventsTable
) D
GROUP BY ID
The method is counting how many records each ID has, and getting the TotalDays by date differences (in days) between the current the next date, if the difference is less than 10 days, then give me 1, else give me 0.
Then compare, if the total days equal the number of records that each ID has (minus one) would print Active, else Inactive.
This is just another approach that doesn't use CTE.
I have created a calculated column but it is giving me a row with null value. If I add another calculated field, it adds 2 null rows, and so on.
My objective is to get a single row with a single value. No nulls.
The code:
SELECT
CLIENT_CODE,
( CASE WHEN CLITBP.TBPCODIGO=101 THEN COALESCE( CLITBP.TBPDESC2,0) ELSE NULL END) TAB101
FROM
CLIENT
GROUP BY 1,2
the wrong output
the intended output
If you want one row per client code, then you should have only one key in the GROUP BY. Perhaps this is what you want:
SELECT CLIENT_CODE,
MAX(CASE WHEN CLITBP.TBPCODIGO = 101 THEN COALESCE(CLITBP.TBPDESC2, 0) END) as TAB101
FROM CLIENT
GROUP BY CLIENT_CODE;
My Fact table looks like this:
ticketID price statusID
1 100 1
2 100 1
2 100 2
3 150 1
I am using SSAS to create an OLAP Cube for my data warehouse.
I cannot use the aggregateFunction 'Sum' for the measure 'total price', because I will get 450$ instead of 350$ (which is the correct tatal)
Regards
Then you can still add a view in db like this:
select
ticketid,
price,
statusid,
case when rn=1 then 1 else 0 end as IsMaxStatus
from
(select ticketid,price,statusid,
row_number()over
(partition by ticketid, price order by statusid desc) as rn
from yourFactTb
) as fact
Then add a dimension [IsMaxStatus] which inlcuded two records of 0/1 in your cube and set the Dim-usage as regular with that measure-group depended on above fact table, and then add a calculated measure say [cal-price] with below formula:
with member [cal-price] as
([Price],[IsMaxStatus].[IsMaxStatus].&[1])
select [cal-price] on 0
from [YourCube]
You can also calculate other measure by this measure-group without the filter of dim [IsMaxStatus]
Hope it helps.
www.mdx-helper.com