get number of records on the basis of one value - sql

Input table
Col
1
2
3
4
5
Output
1
2
2
3
3
3
4
4
4
4
5
5
5
5
5
Is there any way this could be achieved in sql without writing any function ?

You could use a self join approach:
SELECT t1.Col
FROM yourTable t1
INNER JOIN yourTable t2
ON t2.Col <= t1.Col
ORDER BY t1.Col1;
The logic here is that each original Col value gets joined to however many records in the same table which its value represents. If your actual data were not a perfect sequence, the above approach might still be viable, with some changes, with the help of analytic functions.

Related

Find rows that contains same value on different columns

The table to find which rows contains same value on two different columns for 2 rows. Here is a small sample rows among 2k+ rows.
id left right
1 3 4
2 4 1
3 1 9
4 2 6
5 2 5
6 9 8
7 0 7
In the above case, I need to get row 1,2,3,6 as it contains 4 on two rows of two different columns i.e (id=1&2),1 on two rows of two different columns(id=1&3) and 9 on two rows of two different columns(id=3&6)
My thoughts:
I did thought many things for example cross join on left and right column, group by and count etc.
with Final as (With OuterTable as (WITH Alias AS (SELECT id as left_id , left FROM Test)
SELECT DISTINCT id, left_id FROM Alias
INNER JOIN Test ON Alias.left = Test.right)
SELECT id from OuterTable
UNION ALL
SELECT left_id from OuterTable)
SELECT DISTINCT * from Final;
It's messy, but it works.
You can do it with EXISTS:
SELECT t1.*
FROM tablename t1
WHERE EXISTS (
SELECT 1 FROM tablename t2
WHERE t1.id <> t2.id AND (t2.left = t1.right OR t1.left = t2.right)
)
See the demo.
Results:
id
left
right
1
3
4
2
4
1
3
1
9
6
9
8

Access Top N Query where N is given in another table

I have two tables in MS SQL Server. Table2 has the following:
TaskId TopN
1 2
2 3
3 1
Table1 has the following:
TaskId TopN Value
1 2 12
1 2 12
1 2 12
2 3 1
2 3 1
2 3 5
2 3 12
2 3 8
2 3 5
I want to be able to select the top N records based on the TopN field in table2 (which is the same TopN value found in table1, so maybe I don't even need to bother using two tables). The desired output should be as follows:
TaskId TopN Value
1 2 12
1 2 12
2 3 12
2 3 8
2 3 5
I have tried the below SQL statement, but it skips TaskId=1. Any idea of what I am doing wrong?
SELECT DISTINCT T1.TaskId,
T1.TopN,
T1.values
FROM Table1 T1 INNER JOIN Table1 T2 ON
T1.TaskId = T2.TaskId AND
T1.TopN = T2.TopN AND
T1.Value <= T2.Value
GROUP BY T1.TaskId,
T1.TopN,
T1.Value
HAVING COUNT(*) <= (
SELECT TopN
FROM table2
WHERE table2.TaskID = T1.TaskId
)
Please note that in the question you have named Table2 as the one which has the fields - TaskId, TopN, Values however in your query you have used the opposite. Assuming Table2 is the one which has the details, you can use the query below to get the desired result. You would not need to use the other table (Table1 - as per the question) which has just the task_id and topN since all the info is already present in Table2.
Select Taskid, TopN, Values
from
(Select T1.*, row_number() over(partition by Taskid order by Values desc) As rnk
from Table2 T1) Tb
where Tb.TopN >= Tb.rnk;
** Fixed the typo in the code (changed to >= instead of <=), it should work fine now.
The problem is that you have three rows with the same values -- and 3 > 2. That is, the subquery returns "3" which is not less than "2". In SQL Server, you would do this much more simply using row_number().
If you are using MS Access, you need a column that distinguishes the rows.
EDIT:
In SQL Server, you would use:
select t1.*
from (select t1.*,
row_number() over (partition by taskid order by value desc) as seqnum
from table1 t1
) t1
where t1.seqnum <= t1.topn;

Oracle SQL - display values up to current record

Can I use LISTAGG or a similar analytical function in Oracle SQL to display all values in group up to current record?
This is my table:
id group_id value
-- -------- -----
1 1 A
2 1 B
3 1 C
4 2 X
5 2 Y
6 2 Z
I would like the following result:
id group_id values
-- -------- ------
1 1 A
2 1 AB
3 1 ABC
4 2 X
5 2 XY
6 2 XYZ
Here is one option, using a correlated subquery to handle the rollup of the value column:
SELECT
t1.id,
t1.group_id,
(SELECT LISTAGG(t2.val, '') WITHIN GROUP (ORDER BY t2.id)
FROM yourTable t2
WHERE t1.group_id = t2.group_id AND t2.id <= t1.id) AS vals
FROM yourTable t1
ORDER BY
t1.id;
Demo
The logic here is that, for each group, with rollup a concatenation of all values coming at or before the current id value in a given row.
Another approach to this, one which might perform and scale better, would be to use a recursive CTE. But, that would take more code, and might be harder to digest than what I wrote above.

SQL Server : count how many times one

I am learning SQL and I am stuck with a certain question for a while. I have a huge data set looking like:
id v1
1 3
2 3
3 -
4 5
5 3
6 5
7 3
I need to count how many times each id is in v1. The output i seek is:
id count
1 0
2 0
3 4
4 0
5 2
6 0
7 0
Have been looking for an answer on many forums. The problem is that there are a lot of ids so that I can`t search by number "1" and so on. If I use something like id=v1 i get how many times a row has equal values in these columns. Looking for some help. Please.
Try this:
SELECT t1.id, COUNT(t2.v1)
FROM mytable AS t1
LEFT JOIN mytable AS t2 ON t1.id = t2.v1
GROUP BY t1.id
ORDER BY t1.id
Demo here

why 9 rows are fetch from this query?

Given 2 tables T1 and T2.
T1 T2
A 1
B 2
C 3
You make a query SELECT * FROM T1, T2.
What is the no: of rows that are fetched from this query?
Answer is 9
This query results in cartesian product because no other conditions are provided. Every row from first table is matched with every row from second table.
The result is
A 1
A 2
A 3
B 1
B 2
B 3
C 1
C 2
C 3
Because each record from the first table is returned along with each record of the second table and the result is not filtered.
The exact output will be:
T1 T2
A 1
A 2
A 3
B 1
B 2
B 3
C 1
C 2
C 3
(order may vary)
It is a cartesian product: select all rows from one table (3) and all rows from another table (3) and combine them, so 3*3=9.
That's what you asked it to do. You got all the rows from T1 and all the rows from T2. They don't just get added together -- that won't work if the columns are different, for example, though you can do this with UNION -- they get merged in what's known as a "cartesian product". You essentially get all combinations of rows from both tables. And 3*3 = 9.