SQL add to select the sum of equal values - sql-server

SELECT
hg.referencia AS Referencia,
hg.toleInf AS Min,
hg.toleSup AS Max,
ROUND(CAST((hrg.x1+hrg.x2+hrg.x3+hrg.x4)/4 AS FLOAT),2) AS X,
COUNT(hg.Referencia) AS NumGraficos
FROM hRegGeometrias hrg
JOIN hGeometria hg
ON hrg.idGeometria = hg.idGeom
WHERE hrg.idMatriz = 2
GROUP BY hg.referencia, hg.toleInf, hg.toleSup, hrg.x1, hrg.x2, hrg.x3, hrg.x4, hrg.idRegisto
ORDER BY Referencia, IdRegisto ASC
which returns this
what i expect is that it sums the column Referencia but only distinct value, like for example, the sum should be 2 because there's only
'M130342'
'M130344'
So in the column NumGraficos, i would expect the value to be 2.
How to achieve this?
Referencia Min Max X NumGraficos
M130342 2 7 9,81 1
M130342 2 7 9,8 1
M130342 2 7 3,25 1
M130342 2 7 1,75 1
M130342 2 7 3,13 1
M130344 1 7 2 1
M130344 1 7 4,75 1
M130344 1 7 3,25 1
EDIT
It's probably impossible to get the result I expect since this database relations are messed up. I will try a different approach by returning some values separatedly

Related

Find the number of transitions for certain value within a list of values

I have a table include "ID" and "Values", and wanted to know how many times does value "A" jumped into another values like below
ID
Values
1
A
1
A
1
A
1
B
1
A
1
B
1
B
1
C
1
C
1
C
1
A
2
A
2
A
2
B
2
A
2
B
2
C
2
B
Expected Result:
ID
Values
Desired Output
1
A
0
1
A
0
1
A
1
1
B
0
1
A
1
1
B
0
1
B
0
1
C
0
1
C
0
1
C
0
1
A
0
2
A
0
2
A
1
2
B
0
2
A
1
2
B
0
2
C
0
2
B
0
The final table should be like this:
ID
Number of Transitions
1
2
2
2
You just need LEAD() to look at the next value:
select id, values, lead(value) over(partition by id) next_value
from table
Then you can compare next_value with values, and apply an iff(value='A' and next_value!='A', 1, 0).
Then just SUM() or COUNT() and GROUP BY.
You could also treat this as a regexp problem where you want to count how many times a given pattern occurs for each id. The missing piece in your question is -what column dictates the order in which the values appear for each id? You'll need that for either of the solutions
select id, regexp_count(listagg(val,',') within group (order by ordering_col), 'A,[^A]')
from t
group by id;

SQLite: combination of different ordering policies in one query

I have a table which holds 4 columns: int x, int y, int z, int type.
I need to select sorted list of records when next properties preserved:
All records with type 1 must be ordered by x and y (y is secondary key) in ascending order;
All records of type 2 must be ordered by z. In ascending order.
Records of type 2 usually ordered by x and y and when ordered by z the ordering should be the same. In theory. However, in reality some of type 2 records may be partially disordered with respect to z, i.e. for them table.x2 > table.x1 but table.z2 < table.z1.
I need for all selected records of type 2 to ensure table.z2 > table.z1 even at price of having table.x1 > table.x2 (implied, that table.x1 < table.x2 for all other records).
I figured out some query like this:
SELECT * FROM aTable ORDER BY CASE type WHEN 1 THEN x ASC, y ASC ELSE z ASC END;
but for some reason SQLite rejects it as syntactically wrong.
Is it possible anyway to construct such query?
UPDATE:
Example
Data in table
x y z type
1 4 3 1
2 3 6 1
2 2 6 1
8 3 5 2
4 6 3 2
5 8 6 1
7 6 2 2
Expected result:
1 4 3 1
2 2 6 1
2 3 6 1
7 6 2 2
4 6 3 2
5 8 6 1
8 3 5 2

SQL Server query problem. example is in excel sheet picture

Please see the following pic and i want to convert this formula in SQL Server.
in excel sheet
M N
15 1 0
16 3 1
17 5 2
18 8 4
19 9 4
N= IF(M16-M15<=1,N15,M16-M15-1+N15
Please see the screenshot for reference:
As per your tags, this can be done with LAG and then doing a running total.
For each row, first calculate the difference in M from the previous row (using LAG) - I call this Dif_Last_M. This mirrors the 'M24-M23' part of your formula.
If Dif_Last_M is <= 1, add 0 to the running total (effectively making the running total the same as for the previous row)
Else if Dif_Last_M is > 1, add (Dif_Last_M minus 1) to the running total
Here is the code assuming your source table is called #Temp and has an ID (sorting value)
WITH M_info AS
(SELECT ID, M, (M - LAG(M, 1) OVER (ORDER BY ID)) AS Dif_Last_M
FROM #Temp
)
SELECT ID,
M,
SUM(CASE WHEN Dif_Last_M > 1 THEN Dif_Last_M - 1 ELSE 0 END) OVER (ORDER BY ID) AS N
FROM M_info;
And here are the results
ID M N
1 1 0
2 3 1
3 5 2
4 8 4
5 9 4
6 12 6
7 13 6
Here is a db<>fiddle with the above. It also includes additional queries showing
The result from the CTE
The values used in the running total
Note that while it possible to do this with recursive CTEs, they tend to have performance problems (they are loops, fundamentally). Soit is better (performance-wise) to avoid recursive CTEs if possible.

Eliminate repeated vectors but with elements on different order

I have a matrix A which is (243 x 5). I want to pick the unique row vectors of that matrix but taking into account that row vectors with the same elements but in different order shall be considered as being the same.
E.g., suppose for simplicity that the A matrix is (10 x 5) and equal to:
A=[1 2 1 2 3
1 3 1 1 1
1 3 1 1 2
1 2 1 1 3
2 3 1 2 1
1 3 1 2 2
1 3 1 2 3
1 3 1 3 2
1 3 1 3 1
1 3 2 3 1]
On the example above, rows (1, 5, 6) are to be considered equivalent they have the same elements but in different order. Also, rows (3 and 4) are equivalent, and rows (7, 8, 10) are also equivalent.
Is there any way to write a code that removes all "repeated rows", i.e. a code that delivers only the rows (1, 2, 3, 7 and 9) from A?
So far I came across with this solution:
B(:,1) = sum(A == 1,2);
B(:,2) = sum(A == 2,2);
B(:,3) = sum(A == 3,2);
[C, ia, ic] = unique(B,'rows');
Result = A(ia,:);
This delivers what I am looking for with one caveat - it is delivering the unique rows of A according to the criteria defined above, but it is not delivering the first row it finds. I.e. instead of delivering rows (1,2,3,7,9) it is delivering rows(7, 1, 9, 3, 2).
Anyway I can force him to deliver the rows in correct order? Also any better way of doing this?
You can do it as follows:
Sort A along the second dimension;
Get stable indices of unique (sorted) rows;
Use the result as row indices into the original A.
That is:
As = sort(A, 2);
[~, ind] = unique(As, 'rows', 'stable');
result = A(ind,:);
For
A = [1 2 1 2 3
1 3 1 1 1
1 3 1 1 2
1 2 1 1 3
2 3 1 2 1
1 3 1 2 2
1 3 1 2 3
1 3 1 3 2
1 3 1 3 1
1 3 2 3 1];
this gives
result =
1 2 1 2 3
1 3 1 1 1
1 3 1 1 2
1 3 1 2 3
1 3 1 3 1

Case statement not correctly matching expected values

I'm trying to generate some randomized data, and I've been using newid() to seed functions since it is called once for every row and is guaranteed to return a different result each time. However I'm frequently getting values that are somehow not equal to any integers in the expected range.
I've tried a few variations, including a highly upvoted one, but they all result in the same issue. I've put it into a script that shows the problem:
declare #test table (id uniqueidentifier)
insert into #test
select newid() from sys.objects
select
floor(rand(checksum(id)) * 4),
case isnull(floor(rand(checksum(id)) * 4), -1)
when 0 then 0
when 1 then 1
when 2 then 2
when 3 then 3
when -1 then -1
else 999
end,
floor(rand(checksum(newid())) * 4),
case isnull(floor(rand(checksum(newid())) * 4), -1)
when 0 then 0
when 1 then 1
when 2 then 2
when 3 then 3
when -1 then -1
else 999
end
from #test
I expect the results to always be in the range 0 to 3 for all four columns. When the unique identifiers are retrieved from a table, the results are always correct (first two columns.) Similarly, when they're output on the fly they're also correct (third column.) But when they're compared on the fly to integers in a case statement, it often returns a value outside the expected range.
Here's an example, these are the first 20 rows when I ran it just now. As you can see there are '999' instances in the last column that shouldn't be there:
0 0 3 1
3 3 3 1
0 0 3 3
3 3 2 999
1 1 2 999
3 3 2 1
2 2 0 999
0 0 0 0
3 3 2 0
1 1 3 999
3 3 0 999
2 2 2 2
1 1 3 0
2 2 3 0
3 3 1 999
0 0 1 999
3 3 1 1
0 0 0 3
3 3 0 999
0 0 1 0
At first I thought maybe the type coercion was different than I expected, and the result of rand() * int was a float not an int. So I wrapped it all in floor to force it to be an int. Then I thought perhaps there's an odd null value creeping in, but with my case statement a null would be returned as -1, and there are none.
I've run this one two different SQL Server 2012 SP1 instances, both give the same sort of results.
In the fourth column, isnull(floor(rand(checksum(newid())) * 4), -1) is being evaluated up to five times for each row. Once for each branch of the case. On each call the values can be different. So it can return 2, not match 1, 3 not match 2, 1 not match 3, 3 not match 4 fall to the else and return 999.
This can be seen if you get the execution plan, and look at the XML, there is a line [whitespace added.]:
<ScalarOperator ScalarString="
CASE WHEN isnull(floor(rand(checksum(newid()))*(4.000000000000000e+000)),(-1.000000000000000e+000))=(0.000000000000000e+000) THEN (0)
ELSE CASE WHEN isnull(floor(rand(checksum(newid()))*(4.000000000000000e+000)),(-1.000000000000000e+000))=(1.000000000000000e+000) THEN (1)
ELSE CASE WHEN isnull(floor(rand(checksum(newid()))*(4.000000000000000e+000)),(-1.000000000000000e+000))=(2.000000000000000e+000) THEN (2)
ELSE CASE WHEN isnull(floor(rand(checksum(newid()))*(4.000000000000000e+000)),(-1.000000000000000e+000))=(3.000000000000000e+000) THEN (3)
ELSE CASE WHEN isnull(floor(rand(checksum(newid()))*(4.000000000000000e+000)),(-1.000000000000000e+000))=(-1.000000000000000e+000) THEN (-1)
ELSE (999)
END
END
END
END
END
">
Placing the expression in a CTE seems to keep the recomputes from happening:
; WITH T AS (SELECT isnull(floor(rand(checksum(newid())) * 4), -1) AS C FROM #Test)
SELECT CASE C
when 0 then 0
when 1 then 1
when 2 then 2
when 3 then 3
when -1 then -1
else 999 END
FROM T

Resources