I want to do a sequential sum in a table by taking into consideration a few extra conditions.
We need to make sure that when the sum is taken sequentially so if a id has +40 then the next sum would be 130, if the next one is +1, the sum is still 130, now if the next one is -1 then the sum has to be 129.
100 needs to be added to the sum for the first time and from there on just the count should be added depending on condition.
We need to even cap the min value of sum so it can't be less than 70
I have tried the query below but it does not seem to look at the prior value.
Example that I tried:
create table tableA (id int not null, count int not null);
insert into tableA(id, count) values(1,11), (2,21),(3, -3); -- case 1
insert into tableA(id, count) values(1,35), (2,-3); -- case 2
insert into tableA(id, count) values(1,-45),(2,67); -- case3
Query tried:
select t.id, t.count,
case when (100+(select ifnull(sum(count),0) from tableA x where x.id <= t.id)) >= 130 then 130
when (100+(select ifnull(sum(count),0) from tableA x where x.id <= t.id)) <= 70 then 70
else (100+(select ifnull(sum(count),0) from tableA x where x.id <= t.id))
end as xxxx
from tableA t;
I expect my output to look like:
Case1 Result:
id count Sum
1 11 111
2 21 130
3 -4 126
Case2 Result:
id count Sum
1 35 130
2 -3 127
Case3 Result:
id count Sum
1 -45 70
2 67 137
THIS ANSWERS THE ORIGINAL VERSION OF THE QUESTION.
I think this does what you want:
select a.*, (#sum := least(#sum + count, 130)) as "sum"
from (select a.*
from tablea a
order by a.id
) a cross join
(select #sum := 0) params;
I don't understand where the 100 is coming from. It is not part of your explanation.
Here is a db<>fiddle that illustrates how this works using 30 as the limit (which seems to be your intention).
I want to carry down the value of a variable from row 1 to row 2, use it for a calculation in row 2 and then take the output to row 3 in my query. The process repeats for 1000s of rows. Retain does this in SAS, how do I do it in MySql?
In SQL, you would use subqueries for in-between observations calculations and relate values between the nested and main query. Since typical uses of the RETAIN statement in SAS involves running totals, counting number of value occurrences, setting indicators within a BY-group, nested subqueries can replicate such functionality.
The below example demonstrates running aggregates across grouped observations.
Example table
id group name amount
1 Object-oriented Java 100
2 Object-oriented C# 50
3 Object-oriented Python 75
4 Object-oriented PHP 65
5 Special Purpose SQL 80
6 Special Purpose XSLT 60
7 Statistical R 85
8 Statistical SAS 100
Query with two subqueries for running counts and running sums:
SELECT t1.id, t1.group, t1.name, t1.amount,
(SELECT Count(*) FROM maintable As t2
WHERE t1.group = t2.group AND t1.id >= t2.id) As RunningCount,
(SELECT Sum(t3.amount) FROM maintable As t3
WHERE t1.group = t3.group AND t1.id >= t3.id) As RunningAmount
FROM maintable As t1
Output
id group name amount RunningCount RunningAmount
1 Object-oriented Java 100 1 100
2 Object-oriented C# 50 2 150
3 Object-oriented Python 75 3 225
4 Object-oriented PHP 65 4 290
5 Special Purpose SQL 80 1 80
6 Special Purpose XSLT 60 2 140
7 Statistical R 85 1 85
8 Statistical SAS 100 2 185
In MySQL, you would do this using variables. Here is an example to calculate the row number:
select t.*, (#rn := #rn + 1) as rn
from table t cross join
(select #rn := 0) params
order by col;
Let's suppose I have this MySQL table:
id place_id area_mq n
-- -------- ------- --
1 1 50 1
2 2 90 1
3 2 20 1
4 3 10 1
5 3 10 2
6 3 10 3
7 4 20 1
8 4 20 2
9 5 15 1
10 5 25 1
id is the primary key, place_id stands for an area id, area_mq is the surface area of the place in mq.
What I have to do is find a compact query to calculate the sum of area_mq with these rules:
if n is equal for the same place_id, then count every area_mq (f.ex for place_id=2, I count 90 and 20 in the sum)
if n is different for the same place_id, then count area_mq only once (possible to do because for these kind of "places" the value will be the same; f.ex. place_id=4, there are two 20's, i sum only 20 and not 40).
In this example, my correct total would be: 50 + (90 + 20) + 10 + 20 + (15 + 25).
Can I accomplish this with a query (no code or procedures)? If requirements for n were reversed, it would be simple with a GROUP BY and a subquery... but with these conditions, I'm stuck.
select place_id, sum(area_sq)/count(distinct n)
from your_table
group by place_id;
Tested here
From what I see in your pattern all with n = 1 is added?
SELECT SUM((n = 1) * area_mq) AS total
FROM table_name
I do a validation that either returns 1 or 0, and then I multiply it with the column value.
I think you could use something like this. Take the sum and the count of n, and also the min and max (maybe overkill); use that to figure out if all values of n are the same. Along these lines:
SELECT
CASE WHEN sm/cnt = mn AND sm/cnt = mx THEN sum_area
ELSE area/cnt END
AS sum_area
FROM (
SELECT COUNT(n) cnt, SUM(n) sm, MIN(n) mn, MAX(n) mx, SUM(area_mq) sum_area
GROUP BY place_id
) a
So, say n has values of 2 and 2 => sm/cnt = mn (4/2 = 2) and mx. If it has values of 2 and 1 => sm/cnt != mn (3/2 != 1).
I have a table of data in MS Access 2007. There are 6 fields per record, thousands of records. I want to make a sort of pivot table like object. That is, if any two rows happens to be the same in the first 4 fields, then they will end up grouped together into one row. The column headers in this pivot table will be the values from the 5th field, and the value in the pivot table will be the 6th field, a dollar amount. Think of the 5th field as letters A, B, C, D, E, F, G. So, the table I start with might have a row with A in the 5th field and $3.48 in the 6th field. Another row may match in the first 4 fields, have B in the 5th field and $8.59 in the 6th field. Another may match in the first 4 fields, have E in the 5th field and $45.20 in the 6th field. I want all these rows to be turned into one row (in a new table) that starts with the first 4 fields where they match, then lists $3.48, $8.59, $0.00, $0.00, $45.20, $0.00, $0.00, corresponding to column headers A, B, C, D, E, F, G (since no records contained C, D, F, G, their corresponding values are $0.00), and then ends with one more field that totals up the money in that row.
Currently, I have some VBA code that does this, written by someone else a few years ago. It is extremely slow and I am hoping for a better way. I asked a previous question (but not very clearly so I was advised to create a new question), where I was asking if there was a better way to do this in VBA. My question asked about reading and writing large amounts of data all at once in Access through VBA, which I know is a good practice in Excel. That is, I was hoping to take my original table and just assign the entire thing to an array all at once (as in Excel, instead of cell by cell), then work with that array in VBA and create some new array and then write that entire array all at once to a new table (instead of record by record, field by field). From the answers in that question, it seems like that is not really a possibility in Access, but my best bet might be to use some sort of query. I tried the Query Wizard and found the Cross Tab query which is close to what I describe above. But, there appears to be a max of 3 fields used in the Row Heading, whereas here I have 4. And, instead of putting $0.00 when a value is not specified (like C, D, F, G in my example above), it just leaves a blank.
Update (in response to Remou's comment to give sample data): Here is some sample data.
ID a b c d e f
7 1 2 3 5 A 5
8 1 2 3 5 B 10
9 1 2 3 5 C 15
10 1 2 3 5 D 20
11 1 2 3 5 E 25
12 1 2 4 4 A 16
13 1 2 4 4 B 26
14 1 3 3 7 D 11
15 1 3 3 7 B 11
The result should be:
a b c d an bn cn dn en Total
1 2 3 5 5 10 15 20 25 75
1 2 4 4 16 26 0 0 0 42
1 3 3 7 0 11 0 11 0 22
But, when I copy and paste the SQL given by Remou, the only output I get is
a b c d an bn cn dn en
1 2 3 5 5 10 15 20 25
This is, I think, what you want, but it would be better to consider database design, because this is a spreadsheet-like solution.
SELECT t0.a,
t0.b,
t0.c,
t0.d,
Iif(Isnull([a1]), 0, [a1]) AS an,
Iif(Isnull([b1]), 0, [b1]) AS bn,
Iif(Isnull([c1]), 0, [c1]) AS cn,
Iif(Isnull([d1]), 0, [d1]) AS dn,
Iif(Isnull([e1]), 0, [e1]) AS en
FROM (((((SELECT DISTINCT t.a,
t.b,
t.c,
t.d
FROM table3 t) AS t0
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS a1
FROM table3 t
WHERE t.e = "A") AS a0
ON ( t0.d = a0.d )
AND ( t0.c = a0.c )
AND ( t0.b = a0.b )
AND ( t0.a = a0.a ))
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS b1
FROM table3 t
WHERE t.e = "B") AS b0
ON ( t0.d = b0.d )
AND ( t0.c = b0.c )
AND ( t0.b = b0.b )
AND ( t0.a = b0.a ))
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS c1
FROM table3 t
WHERE t.e = "C") AS c0
ON ( t0.d = c0.d )
AND ( t0.c = c0.c )
AND ( t0.b = c0.b )
AND ( t0.a = c0.a ))
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS d1
FROM table3 t
WHERE t.e = "D") AS d0
ON ( t0.d = d0.d )
AND ( t0.c = d0.c )
AND ( t0.b = d0.b )
AND ( t0.a = d0.a ))
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS e1
FROM table3 t
WHERE t.e = "E") AS e0
ON ( t0.d = e0.d )
AND ( t0.c = e0.c )
AND ( t0.b = e0.b )
AND ( t0.a = e0.a );
Table3
ID a b c d e f
1 1 2 3 4 a €10.00
2 1 2 3 4 b €10.00
3 1 2 3 4 c €10.00
4 1 2 3 4 d €10.00
5 1 2 3 4 e €10.00
6 1 2 3 5 a €10.00
7 1 2 3 5 b
8 1 2 3 5 c €10.00
9 1 2 3 5 d €10.00
10 1 2 3 5 e €10.00
Result
There are two rows, because there are only two different sets in the first four columns.
a b c d an bn cn dn en
1 2 3 4 €10.00 €10.00 €10.00 €10.00 €10.00
1 2 3 5 €10.00 €0.00 €10.00 €10.00 €10.00
The way the sql above is supposed to work, is that it selects each of the four definition columns and the currency column from the table where the sort column has a particular sort letter and labels the currency column with the sort letter, each of these sub queries are then assembled, however, you can take a sub query and look at the results. The last one is the part between the parentheses:
INNER JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS e1
FROM table3 t
WHERE t.e = "E") AS e0
i have table columns one (idprocess) point to columns two (idporcess1) and point to columns tree (idprocess2).
id idprocess idporcess1 idprocess2
1 15 16 17 <== A
2 15 16 19 <== B
3 15 20 23
4 14 16 17
6 16 15 80 <== C
7 17 15 49 <== D
8 23 16 20 <== E
I need a SQL query that returns this: row c and row D, so with number idprocess(16) and idprocess(17 )
because row c : idprocess(16) references again ipdprocess1(15)
because row c : idprocess(17 ) references agin ipdprocess1(15)
please help
i want only to eleminate circular referencial in tree
If you are happy to find rows where the first two columns are permutated, this will do the job:
SELECT *
FROM my_tbl t
WHERE EXISTS (SELECT 1 FROM my_tbl t1 WHERE t1.idprocess = t.idprocess1 AND t1.idprocess1 = t.idprocess)
ORDER BY t.id;
Alternative interpretation:
If you want all rows where idprocess1 has been listed in idprocess before (before = smaller id), then you can:
SELECT *
FROM my_tbl t
WHERE EXISTS (SELECT 1 FROM my_tbl t1 WHERE t1.id < t.id AND t1.idprocess = t.idprocess1)
ORDER BY t.id;
You wouldn't call that "permutation", though.
The question is a bit ambiguous but I tried to understand it on my own and prepared the following query:
SELECT *
FROM TEMP
where C2 IN ( Select C2 FROM TEMP group by C2 having count(C2) > 1 )
OR C3 IN ( Select C3 FROM TEMP group by C3 having count(C3) > 1 )