Find all parent and child with a relationship table - sql

I have inherited two tables:
Table 1: Loc
LocID Field1 Field2
---------------------------
1 AAA BBB
2 CCC DDD
3 EEE FFF
4 GGG HHH
5 III JJJ
6 KKK LLL
7 MMM NNN
8 OOO PPP
9 QQQ RRR
10 SSS TTT
11 UUU VVV
Table 2: LocRel
LocID_A LocID_B
-----------------------
1 2
1 3
2 4
2 5
3 6
3 7
5 11
8 9
8 10
So, the LocRel table basically is used to specified the relationships between the various records in the Loc table.
I am struggling with writing a sql statement that will list all the relationships like so:
LocID Level LocIDH_Ancestry Field1 Field2
---------------------------------------------------
1 1 NULL AAA BBB
2 2 1 CCC DDD
3 2 1 EEE FFF
4 3 1,2 GGG HHH
5 3 1,2 III JJJ
6 3 1,3 KKK LLL
7 3 1,3 MMM NNN
8 1 NULL OOO PPP
9 2 8 QQQ RRR
10 2 8 SSS TTT
11 4 1,2,5 UUU VVV
I am not good at all in queries involving relationships, and would really appreciate some help on how the above can be achieved.
Thank you to all!

This answer may be SQL Server specific. I'm not an expert in SQL, so I don't know how much of this is standard and/or adopted in other dbms.
You can implement the kind of queries you mentioned, using recursive queries. Here is a intro to the subject that provides a good starting point.
For your specific query, something like this should do the work.
WITH MyCTE AS
(
SELECT
LocID, 1 as Level,
NULL as LocIDH_Ancestry,
Field1, Field2
FROM
Table1
WHERE
LocID NOT IN (SELECT LocID_B FROM Table2)
UNION ALL
SELECT
t1.LocID,
c.Level + 1 as Level,
t2.LocID_A as LocIDH_Ancestry,
t1.Field1, t1.Field2
FROM
Table1 t1
INNER JOIN
Table2 t2 ON t1.LocID = t2.LocID_A
INNER JOIN
MyCTE c ON t2.LocID_B = c.LocID
)
SELECT *
FROM MyCTE
Hope that helps.

Related

Pagination Logic - Oracle

As I'm new to oracle, not sure how to handle the pagination logic.
I need a query that returns the results based on the start vale and the limit value.
See the below resultset
id name
1 abc
2 def
3 ghi
4 jkl
5 qqq
6 www
7 eee
8 ttt
9 yyy
10 uuu
11 iii
12 ppp
13 aaa
14 sss
15 ddd
16 fff
17 ggg
18 hhh
19 jjj
20 kkk
For suppose if I give the values start value = 0 and limit = 5
then it should return the below records
id name
1 abc
2 def
3 ghi
4 jkl
5 qqq
if start value = 5 and limit = 15 , then I should return the below result
id name
5 qqq
6 www
7 eee
8 rrr
9 ttt
10 yyy
11 uuu
12 iii
13 ooo
14 ppp
15 ddd
16 fff
17 ggg
18 hhh
19 jjj
Please help me with the query
Please let me know if anything.
Thanks
Probably best to use bind variables for this. If you are not familiar with Oracle bind variables, spend 15 minutes reading about them, they are super helpful.
select id, name
from your_table
where id between :start_value and :start_value + :limit_value - 1;

Sql query for combination two tables

Let say, I have two tables
Table 1:
code|name
121 ab
456 qw
Table 2 :
Kode_ak|Nama_ak
1 Bursa
2 Kustodian
3 Kliring
4 Assurance
5 Bunga
I want to combine those two tables. The result will be like this:
Kode_AK|Nama_ak |code|name
1 Bursa 121 ab
2 Kustodian 121 ab
3 Kliring 121 ab
4 Assurance 121 ab
5 Bunga 121 ab
1 Bursa 456 qw
2 Kustodian 456 qw
3 Kliring 456 qw
4 Assurance 456 qw
5 Bunga 456 qw
How can I do it?
You would do this using cross join:
select *
from table1 cross join
table2;
select t3.Kode_AK,t3.Nama_ak,t1.code,t1.name from [dbo].[Table_1] t1 cross join [dbo].[Table_3] t3

DB2:how to get top

I have a table having data like
pin id name
3 33 jjj
2 22 bbb
1 111 aaaa
1 112 aa
1 113 aaa
4 44 kkk
I want to print rows of the table where if count(*) group by pin =1 (i.e single entry in table ) print the row
if count(*) group by pin >2 then print first two rows
so my out put should be
pin id name
3 33 jjj
2 22 bbb
1 111 aaaa
1 112 aa
4 44 kkk
Use row_number() OVER(partion by pin order by id) as rownum function . Where rownum <3
. As #Clockwork-Muse said, you need to define an order becase you need to say what do you want to see if there are more than 2 rows for a particular pin.
This will generate you desired output.

Select max date No result I want

SELECT
mat.matid,
MAX (to_date(to_char (matdatetable.matdateupdate,'yyyy-mm-dd'),'yyyy-mm-dd')),
mat.matuserid,
mat.matname,
mat.matprice
FROM
matdatetable
LEFT JOIN mat ON matdatetable.sourceid = mat.matid
RESULT
matid matdate update matuserid matname matprice
-------------------------------------------------------------
1 2012-01-01 0:0:0:0 0111-1 aaa 100
1 2012-08-01 0:0:0:0 0111-1 aaa 125
1 2013-08-30 0:0:0:0 0111-1 aaa 150
2 2012-01-01 0:0:0:0 0222-1 bbb 130
2 2012-08-21 0:0:0:0 0222-1 bbb 110
2 2013-07-30 0:0:0:0 0222-1 bbb 100
3 2012-01-01 0:0:0:0 0565-1 ccc 100
3 2013-09-30 0:0:0:0 0565-1 ccc 230
But I want to. Results
matid matdate update matuserid matname matprice
------------------------------------------------------------------
1 2013-08-30 0:0:0:0 0111-1 aaa 150
2 2013-07-30 0:0:0:0 0222-1 bbb 100
3 2013-09-30 0:0:0:0 0565-1 ccc 230
SELECT DISTINCT ON (1)
t.sourceid AS matid
,t.matdateupdate::date AS matdate_update
,m.matuserid
,m.matname
,m.matprice
FROM matdatetable t
LEFT JOIN mat m ON m.matid = t.sourceid
ORDER BY 1, t.matdateupdate DESC;
Gives you the latest (according to matdateupdate) entry per sourceid. Your question isn't clear what you want exactly.
Using sourceid rather than matid, since you have a LEFT JOIN and matid could be NULL. Or your use of LEFT JOIN is incorrect ...
Explanation for DISTINCT ON in this related answer:
Select first row in each GROUP BY group?
t.matdateupdate::date casts your timestamp (assuming for lack of information) to date. That seems to be what you want. If you really need the redundant time 00:00, use datetrunc('day', t.matdateupdate) instead.

MSAccess: Ranking rows based upon column criteria

I have a dataset that looks like this:
Account Cost Centre TransNo
aaa 111 43443
aaa 111 32112
aaa 111 43211
aaa 112 32232
aaa 113 56544
bbb 222 43222
bbb 222 98332
ccc 111 88778
I need a column added that is a counter of the number of rows that relate to that Account/Cost Centre combination:
Account Cost Centre TransNo rCounter
aaa 111 43443 1
aaa 111 32112 2
aaa 111 43211 3
aaa 112 32232 1
aaa 112 56544 2
bbb 222 43222 1
bbb 222 98332 2
ccc 111 88778 1
Is this possible to do in MSAccess using SQL? and how would I go about it (ie what would be the SQL script I would need to write)?
Thanks in advance.
Something like:
SELECT a.Account, a.[Cost Centre], a.TransNo, (SELECT Count(*)
FROM table4 b
WHERE b.Account=a.Account
AND b.[Cost Centre]=a.[Cost Centre]
AND b.TransNo<=a.TransNo) AS AccountNo
FROM Table4 AS a
ORDER BY a.Account, a.[Cost Centre], a.TransNo;