How to get the last non empty value of a hierarchy? - sql

I've got a hierarchy with the appropriate value linked to each level, let's say :
A 100
A1 NULL
A2 NULL
B
B1 NULL
B2 1000
B21 500
B22 500
B3 NULL
This hierarchy is materialized in my database as a parent-child hierarchy
Hierarchy Table
------------------------
Id Code Parent_Id
1 A NULL
2 A1 1
3 A2 3
4 B NULL
5 B1 4
6 B2 4
7 B21 6
8 B22 6
9 B3 4
And here is my fact table :
Fact Table
------------------------
Hierarchy_Id Value
1 100
6 1000
7 500
8 500
My question is : do you know/have any idea of how to get only the last non empty value of my hiearchy?
I know that there an MDX function which could do this job but I'd like to do this in an another way.
To be clear, the desired output would be :
Fact Table
------------------------
Hierarchy_Id Value
1 100
7 500
8 500
(If necessary, the work of flatten the hierarchy is already done...)
Thank you in advance!

If the codes for your hierarchy are correct, then you can use the information in the codes to determine the depth of the hierarchy. I think you want to filter out any "code" where there is a longer code that starts with it.
In that case:
select f.*
from fact f join
hierarchy h
on f.hierarchyId = h.hierarchyId
where not exists (select 1
from fact f2 join
hierarchy h2
on f2.hierarchyId = h2.hierarchyId
where h2.code like concat(h.code, '%') and
h2.code <> h.code
)
Here I've used the function concat() to create the pattern. In some databases, you might use + or || instead.

Related

How to write sql query to generate a group no for each grouped record

following is scenario:
I have data in following format:
entryid , ac_no, db/cr, amt
-----------------------------------------------
1 10 D 5
1 11 C 5
2 01 D 8
2 11 C 8
3 12 D 10
3 13 C 10
4 14 D 5
4 16 C 5
5 14 D 2
5 17 C 2
6 14 D 3
6 18 C 3
I want data in following format:
So far i have acheived the first 3 columns by query
select wm_concat(entryid),ac_no,db_cr,Sum(amt) from t1 group by ac_no,db_cr
wm_Concat(entryid),ac_no, db/cr, Sum(amt), set_id
------------------------------------------------
1 10 D 5 S1
2 01 D 8 S1
1,2 11 C 13 S1
3 12 D 10 S2
3 13 C 10 S2
4,5,6 14 D 10 S3
4 16 C 5 S3
5 17 C 2 S3
6 18 C 3 S3
I want an additional column `set_id` that either shows this S1, S2.. or any number 1,2.. so that the debit & credit entries sets can be identified.
I am making sets of debit and credit entries based on their Ac_no values.
Any little help will be highly appreciated. Thanks
Create a new column say set and give a unique identifier to the particular set. So for example the first three records will have set id S1, next two will have S2 and so on.
To distinguish a transaction from a set you can use column db/cr along with newly added set column. You can identify that the 3rd row is a set since it's transaction type is 'C' whereas the transactions are of type 'D'.
Here I have assumed that your transactions are debit only, if not please provide more details in the question. Hope this helps.

Group By and get top N in Simple SQL

I have following table in SQLite
BANK:
user-id sender-name receiver-name amount
----------------------------------------
1 A B 200
2 A C 250
3 A B 400
4 A B 520
4 A D 120
4 A D 130
4 A B 110
4 A B 300
4 A B 190
4 A C 230
4 A B 110
4 A C 40
4 A C 80
I need to find out top 3 transaction from each receiver. There are multiple solutions provided for several other database which is not compatible with SQLite cause of the use of certain functions like PARTITION and RANK and even user-defined variables.
I need the solution in simple SQL queries to allow use with SQLite.
Expected result:
receiver-name amount
--------------------
B 560
C 1220
D 250
I managed to do it with using only simple function with self-join.
Now you can just update N with your preferred value, for my case top 3, it would be LIMIT 3.
SELECT receiver-name ,(
SELECT SUM(amount) as sum_amount
FROM (
SELECT amount
FROM bank as b2
WHERE b2.receiver-name = b.receiver-name
ORDER BY b2.amount DESC
LIMIT 3
)
) as sum_amount
FROM bank as b
GROUP BY receiver-name

How to pivot output in SQL Server 2012

Input:
Table1->Student details
sno sname scourse sjoindate
1 Ram bsc 11/26/2011
2 Sham bcom 10/06/2010
3 Krishna ba 06/16/2012
Table2->Student marks
sno id marks
1 1 67
1 2 77
1 3 80
1 4 60
1 5 90
Table3->Subjectnames
id subjectname
1 Computerscience
2 Maths
3 Satatistics
4 English
5 Hindi
Table4->Student_feedback_QuestionandAnswer
sno Questions Answers
1 Q1 A1
1 Q2 A2
1 Q3 A3
1 Q4 A4
Expected Output:
sno sname scourse sjoindate Computerscience Maths Statistics English Hindi Questions Answers
1 Ram bsc 11/26/2011 67 77 80 60 90 Q1 A1
Q2 A2
Q3 A3
Q4 A4
In the above tables the rows of Table2 and Table3 can increase and decrease depending on the studentname.
I need tabled to combine the data from all four tables into one result set but I don't know how to use pivot with dynamic header with dynamic column values:
Data from Table3.Subjectname column values should be header column names e.g. Computerscience, Hindi.
Data from Table2.marks should be the value under the header column name e.g. marks for id=1 under Computerscience.
the Questions, Answers column from Table4 should come in result set depending on the value of `Table1.sno'
If you can provide a hint for creating a table using pivot with dynamic header with dynamic column values ,yeah using two tables.
Please let me know for more clarification.

SQL - Referencing 3 tables

This is in relation to my survey application for our team. I have 3 tables in my database related to this problem.
I apologize if the database is not fully normalized.
TBL_CHURCH columns:
1 FAM_CHURCH_SACRMNT_NUM (Primary Key) Int(15)
2 RSPONDNT_NUM
3 SURVYR_NUM
4 QN_NUMBER
5 CHRCHFAMLY_NAME
6 CHRCHFAMLY_ISBAPTIZED
Sample row based on order of columns above:
1 2 3 4 5 6
6422164 76826499 5712 362 Serio Tecson Jr. Yes
TBL_INTRVW columns:
1 QN_NUMBR (Primary Key)
2 SURVYR_NUM
3 ZONE_NUM
4 RSPONDNT_NUM
Sample row based on order of columns above:
1 2 3 4
362 5712 11 76826499
TBL_AREA columns:
1 BRGY_ZONE_NUM (Primary Key)
2 BRGY_CODE
Sample row based on order of columns above:
1 2
11 2A
21 2A
31 2A
The field CRCHFAMLY_ISBAPTIZED has only two values. A "Yes" or a "No" and each row has a QN_NUMBR value that is referenced to TBL_INTRVW and each QN_NUMBR on TBL_INTRVW has a unique ZONE_NUM that is referenced to TBL_AREA and that ZONE_NUM has a corresponding BRGY_CODE. Each BRGY_CODE have at least 2 ZONE_NUM values
My problem is that I want to count the number of people baptized in a given area.
The output more or less should look like this:
(The output is collected from the 3 different ZONE_NUM)
Zone Name Num of People Baptized
2A 20
I'm having what trouble what to use in my SQL statements. Should I use a WHERE within an INNER JOIN? And how do I go about in my SELECT statements?
SELECT c.BRGY_ZONE_NUM,count(a.CHRCHFAMLY_ISBAPTIZED) as [Num of People Baptized]
from TBL_CHURCH a
left join
TBL_INTRVW b
on a.QN_NUMBER=b.QN_NUMBER
left join
TBL_AREA c
on b.ZONE_NUM=cRGY_ZONE_NUM
where a.CHRCHFAMLY_ISBAPTIZED='Yes'
group by c.BRGY_ZONE_NUM
I dont see Zone Name column on the three table, so i used BRGY_ZONE_NUM

Add AUTO INCREMENT column to Sqlite View

I have a table lets called it myTable
tID Name Degree
1 A 23
2 B 55
3 C 77
4 D 45
I want to select only pass Degrees in New View lets call it MyView
The result will be
tID Name Degree
--- ---- --------
2 B 55
3 C 77
But I want myView have sequences start from one by one as follows:
index Name Degree
----- ---- ------
1 B 55
2 C 77
It's possible?
I need to do this because I have a the original table have:
tID sID Name Lesson TryNo Degree
1 1 A a1 1 23
2 1 A a1 2 66
3 2 A b1 1 55
4 2 A b1 2 77
I want to select max tries degree for every lesson exams for each student. ex:
tID sID Name Lesson TryNo Degree
2 1 A a1 2 66
4 2 A b1 2 77
Thanks
I think this is not possible directly since View is just a mirror representation of your tables.
View is created using Select statements, as far as I remember, it is not possible to have a select statement with variables.
Let me know if this works:
CREATE or replace VIEW myView AS
SELECT rownum id,
marks,
name
FROM studentinfo
WHERE degree>50