Why aren't there duplicates in a recursive SQL "range" query? - sql

For reference, here it is:
WITH range_10 AS (
SELECT 1 AS n
UNION ALL
SELECT n+1 AS n
FROM range_10
WHERE n < 10
)
SELECT * FROM range_10;
As we all know and love, this generates a single column n with values from one through ten. However, I am confused about why there aren't duplicate values of n in the output. Here's my understanding of how this query is executed:
Iteration 1
range_10 begins empty
range_10 ends as:
1
Iteration 2
range_10 ends as:
1
2
Iteration 3
range_10 ends as:
1
2
2
3
Why? Because we SELECT'ed n+1 for all rows of the table (there were two of them), then did a UNION ALL, which doesn't remove duplicates. To make this more clear:
Iteration 4
1
2
2
3
2
3
3
4
Does UNION ALL really mean UNION in the context of recursive queries? Or am I missing something more fundamental about recursive queries?

As discussed here the input to each recursive execution is just the result of the previous level, not the cumulative result so far.
The anchor level emits 1. Running the recursive part on that produces 2. Running the recursive part on 2 produces 3, and so on.

Related

postgresql self-join query condition not to return repeat results

I have this simplified query:
SELECT a.p_key, b.p_key
FROM test AS a, test AS b
WHERE
a.p_key != b.p_key -- skip self
AND a.p_key < b.p_key -- symmetry breaker
-- missing extra condition to skip previously fetched results
This is the returned data set. The * marks already 'retrieved' b.p_keys:
a.p_key p.b_key
1 2
1 3
2 3* (already linked to a.p_key = 1)
2 4
3 4* (already linked to a.p_key = 2)
3 5
I have done much research and experimentation but can't seem to reach the result I need:
I want to exclude b.p_keys that have already been retrieved previously, so my actual result set should look like this:
a.p_key p.b_key
1 2
1 3
2 4
3 5
I am a little unclear on the exact purpose of this code, but you can put adjacent pairs in a row using lead():
select p_key, lead(p_key) over (order by p_key) as next_p_key
from test;
This seems to do what you want, although you might want to filter out the last row with NULL:
select p_key, next_p_key
from (select p_key, lead(p_key) over (order by p_key) as next_p_key
from test
) t
where next_p_key is not null

Getting parenthood of tree structure

I am trying to retrieve a tree structure i want specific levels of 'parenthood'. my table has level of depth, pathIndex and mapping. my first approach was to make some kinds of substrings to be able to look for the value via the mapping, but I am getting multiple errors on conversion of strings. one thing that might be possible is that if i try and query an item that is not at the lowest level it should return null for the levels it is missing.
In the table if i where to query for the line while asterisks
Id depth pathindex ItemNumber
4CF91F7F-832E-468D-B44A-E14DC66E710A 0 0 0.0
D34784A3-2134-4D09-828E-0EDA0C275C43 1 1 1
38158804-3EBC-4841-B1AF-1B86AD153010 2 1 1.1
8E25D494-322F-45F9-8A91-2A385F561C71 3 1 1.1.1
**64EB6C43-FF9C-0FF9-133F-01F4F21DA14F** 4 1 1.1.1.1
13AFA35C-80F8-405A-8980-33C3F7733EE2 2 2 1.2
3F1332E9-4D42-4BD8-9423-598430E94CB5 3 1 1.2.1
B3CC1306-A122-46F6-8F67-30FBABA3B590 4 1 1.2.1.1
C3F27C8E-F96B-4498-A85F-E4FC8EA90ED7 4 2 1.2.1.2
This is how it should be looking for the information, the static string are the ones i don't know how to generate in order to get nulls when asking for a level that is not that deep.
Select top 1 VehicleGroupId as Region
from GroupHierarchy where GroupHierarchy.numericalmapping = '1'
Select top 1 VehicleGroupId as gz
from GroupHierarchy where GroupHierarchy.numericalmapping = '1.1'
Select top 1 VehicleGroupId as cedis
from GroupHierarchy where GroupHierarchy.numericalmapping = '1.1.1'
Instead of putting decimals between your hierarchy members rather use forwardslashes (1/2/3) and then you can use Microsoft SQL hiearchy data type and functions to easily join and retain the structure:
https://www.sqlshack.com/use-hierarchyid-sql-server/

How to calculate a progressive sum within an Access query

I have a query, let's call it qry_01, that produces a set of data similar to this:
ID N CN Sum
1 4 0 0
2 3 3 3
5 4 4 7
8 3 3 10
The values shown in this query actually come from a chain of queries and from a bunch of different tables.
The corrected value CN is calculated within the query, and counts N if the ID is not 1, and 0 if it is 1.
The Sum is the value I want to calculate by progressively summing up the CN values.
I tried to use DSUM, but I came out with nothing.
Can anyone please help me?
You could use a correlated subquery in the following way:
select t.id, t.n, t.cn, (select sum(u.cn) from qry_01 u where u.id <= t.id) as [sum]
from qry_01 t

Access SQL query select with a specific pattern

I want to select each 5 rows to be unique and the select pattern applies for the rest of the result (i.e if the result contains 10 records I am expecting to have 2 set of 5 unique rows)
Example:
What I have:
1
1
5
3
4
5
2
4
2
3
Result I want to achieve:
1
2
3
4
5
1
2
3
4
5
I have tried and searched a lot but couldn't find anything close to what I want to achieve.
Assuming that you can somehow order the rows within the sets of 5:
SELECT t.Row % 5, t.Row FROM #T t
ORDER BY t.Row , t.Row % 5
We could probably get closer to the truth with more details about what your data looks like and what it is you're trying to actually do.
This will work with the sample of data you provided
SELECT DISTINCT(thevalue) FROM theresults
UNION ALL
SELECT DISTINCT(thevalue) FROM theresults
But it's unclear to me if it's really what you need.
For instance :
if your table/results returns 12 rows, do you still want 2x5 rows or do you want 2x6 rows ?
do you have always in your table/results the same rows in double ?
There's a lot more questions to rise and no hint about them in what you asked.

Oracle SQL connect by level

Can anyone explain the behavior of the below query:-
select level,t.*
from
( select 'one','two'from dual
union all
select 'one','two'from dual
) t
connect by level<=2
There are 2 rows in the inner query. I was expecting 4 rows of output, but i get 6 rows of output. Why is it so and how does this work?
The query starts with one of your two rows and adds both rows, then it continues with the second row and adds both rows again.
Change your query like this:
select level,t.*
from
( select 'one' from dual
union all
select 'two' from dual
) t
connect by level<=2;
This makes it easier to see what happens:
1 one
2 one
2 two
1 two
2 one
2 two
Read this http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm
When level <= 1, you will get each of the records 1 time.
When level <= 2, then you will get each level 1 time (for level 1) + the number of records in the table
(That means for this condition 2 records having level 1 + 2*2 records having level 2. This is the reason you are getting 6 records.)
CONNECT BY LEVEL gives following number of rows
x+x2+x3+x4+...x^n = Sx^n
where n is number of LEVEL and x is number of rows in a table